Skip to content

Commit 62be913

Browse files
authored
[SYCL] Introduce external arbitrary fixed point functions (#2062)
This change enables support of functions that operate on arbitrary precision fixed point numbers. This datatype and its corresponding operations can be useful on targets that can take advantage of narrower representation such as FPGAs. Arbitrary precision fixed point numbers are represented using arbitrary precision integers (_ExtInt(N) wrapped in ap_int<N>). Additional parameters are: * W - total width of the datatype. It's encoded in the width of the OpTypeInt. * I - determines the position of the decimal point. * S - determines if this is a signed or an unsigned number. Usage example: ap_int<W> a; auto ap_fixed_Sqrt = __spirv_FixedSqrtINTEL<W,rW>(a, S, I, rI); // auto to be deducted to ap_int<rW>
1 parent bc42582 commit 62be913

File tree

3 files changed

+164
-0
lines changed

3 files changed

+164
-0
lines changed

sycl/include/CL/__spirv/spirv_ops.hpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,57 @@ __SYCL_CONVERGENT__ extern SYCL_EXTERNAL void
205205
__spirv_SubgroupBlockWriteINTEL(__attribute__((opencl_global)) uint32_t *Ptr,
206206
dataT Data) noexcept;
207207

208+
template <int W, int rW>
209+
extern SYCL_EXTERNAL ap_int<rW>
210+
__spirv_FixedSqrtINTEL(ap_int<W> a, bool S, int32_t I, int32_t rI,
211+
int32_t Quantization = 0, int32_t Overflow = 0) noexcept;
212+
template <int W, int rW>
213+
extern SYCL_EXTERNAL ap_int<rW>
214+
__spirv_FixedRecipINTEL(ap_int<W> a, bool S, int32_t I, int32_t rI,
215+
int32_t Quantization = 0,
216+
int32_t Overflow = 0) noexcept;
217+
template <int W, int rW>
218+
extern SYCL_EXTERNAL ap_int<rW>
219+
__spirv_FixedRsqrtINTEL(ap_int<W> a, bool S, int32_t I, int32_t rI,
220+
int32_t Quantization = 0,
221+
int32_t Overflow = 0) noexcept;
222+
template <int W, int rW>
223+
extern SYCL_EXTERNAL ap_int<rW>
224+
__spirv_FixedSinINTEL(ap_int<W> a, bool S, int32_t I, int32_t rI,
225+
int32_t Quantization = 0, int32_t Overflow = 0) noexcept;
226+
template <int W, int rW>
227+
extern SYCL_EXTERNAL ap_int<rW>
228+
__spirv_FixedCosINTEL(ap_int<W> a, bool S, int32_t I, int32_t rI,
229+
int32_t Quantization = 0, int32_t Overflow = 0) noexcept;
230+
template <int W, int rW>
231+
extern SYCL_EXTERNAL ap_int<2 * rW>
232+
__spirv_FixedSinCosINTEL(ap_int<W> a, bool S, int32_t I, int32_t rI,
233+
int32_t Quantization = 0,
234+
int32_t Overflow = 0) noexcept;
235+
template <int W, int rW>
236+
extern SYCL_EXTERNAL ap_int<rW>
237+
__spirv_FixedSinPiINTEL(ap_int<W> a, bool S, int32_t I, int32_t rI,
238+
int32_t Quantization = 0,
239+
int32_t Overflow = 0) noexcept;
240+
template <int W, int rW>
241+
extern SYCL_EXTERNAL ap_int<rW>
242+
__spirv_FixedCosPiINTEL(ap_int<W> a, bool S, int32_t I, int32_t rI,
243+
int32_t Quantization = 0,
244+
int32_t Overflow = 0) noexcept;
245+
template <int W, int rW>
246+
extern SYCL_EXTERNAL ap_int<2 * rW>
247+
__spirv_FixedSinCosPiINTEL(ap_int<W> a, bool S, int32_t I, int32_t rI,
248+
int32_t Quantization = 0,
249+
int32_t Overflow = 0) noexcept;
250+
template <int W, int rW>
251+
extern SYCL_EXTERNAL ap_int<rW>
252+
__spirv_FixedLogINTEL(ap_int<W> a, bool S, int32_t I, int32_t rI,
253+
int32_t Quantization = 0, int32_t Overflow = 0) noexcept;
254+
template <int W, int rW>
255+
extern SYCL_EXTERNAL ap_int<rW>
256+
__spirv_FixedExpINTEL(ap_int<W> a, bool S, int32_t I, int32_t rI,
257+
int32_t Quantization = 0, int32_t Overflow = 0) noexcept;
258+
208259
template <typename dataT>
209260
__SYCL_CONVERGENT__ extern SYCL_EXTERNAL dataT __spirv_SubgroupBlockReadINTEL(
210261
const __attribute__((opencl_global)) uint64_t *Ptr) noexcept;

sycl/include/CL/__spirv/spirv_types.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ struct ConstantPipeStorage {
8484
int32_t _PacketAlignment;
8585
int32_t _Capacity;
8686
};
87+
88+
// Arbitrary precision integer type
89+
template <int Bits> using ap_int = _ExtInt(Bits);
8790
#endif // __SYCL_DEVICE_ONLY__
8891

8992
// This class does not have definition, it is only predeclared here.

sycl/test/fpga_tests/ap_fixed.cpp

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
// RUN: %clangxx -I %sycl_include -S -emit-llvm -fsycl-device-only %s -o - | FileCheck %s
2+
//
3+
//==---- ap_fixed.cpp - SYCL FPGA arbitrary precision fixed point test -----==//
4+
//
5+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
6+
// See https://llvm.org/LICENSE.txt for license information.
7+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8+
//
9+
//===----------------------------------------------------------------------===//
10+
11+
#include "CL/__spirv/spirv_ops.hpp"
12+
13+
template <int W, int rW, bool S, int I, int rI>
14+
void sqrt() {
15+
ap_int<W> a;
16+
auto ap_fixed_Sqrt = __spirv_FixedSqrtINTEL<W, rW>(a, S, I, rI);
17+
// CHECK: %{{.*}} = call spir_func signext i5 @_Z[[#]]__spirv_FixedSqrtINTEL{{.*}}(i13 signext %[[#]], i1 zeroext false, i32 2, i32 2, i32 0, i32 0)
18+
}
19+
20+
template <int W, int rW, bool S, int I, int rI>
21+
void recip() {
22+
ap_int<W> a;
23+
auto ap_fixed_Recip = __spirv_FixedRecipINTEL<W, rW>(a, S, I, rI);
24+
// CHECK: %{{.*}} = call spir_func signext i8 @_Z[[#]]__spirv_FixedRecipINTEL{{.*}}(i3 signext %[[#]], i1 zeroext true, i32 4, i32 4, i32 0, i32 0)
25+
}
26+
27+
template <int W, int rW, bool S, int I, int rI>
28+
void rsqrt() {
29+
ap_int<W> a;
30+
auto ap_fixed_Rsqrt = __spirv_FixedRsqrtINTEL<W, rW>(a, S, I, rI);
31+
// CHECK: %{{.*}} = call spir_func signext i10 @_Z[[#]]__spirv_FixedRsqrtINTEL{{.*}}(i11 signext %[[#]], i1 zeroext false, i32 8, i32 6, i32 0, i32 0)
32+
}
33+
34+
template <int W, int rW, bool S, int I, int rI>
35+
void sin() {
36+
ap_int<W> a;
37+
auto ap_fixed_Sin = __spirv_FixedSinINTEL<W, rW>(a, S, I, rI);
38+
// CHECK: %{{.*}} = call spir_func signext i11 @_Z[[#]]__spirv_FixedSinINTEL{{.*}}(i17 signext %[[#]], i1 zeroext true, i32 7, i32 5, i32 0, i32 0)
39+
}
40+
41+
template <int W, int rW, bool S, int I, int rI>
42+
void cos() {
43+
ap_int<W> a;
44+
auto ap_fixed_Cos = __spirv_FixedCosINTEL<W, rW>(a, S, I, rI);
45+
// CHECK: %{{.*}} = call spir_func signext i28 @_Z[[#]]__spirv_FixedCosINTEL{{.*}}(i35 %[[#]], i1 zeroext false, i32 9, i32 3, i32 0, i32 0)
46+
}
47+
48+
template <int W, int rW, bool S, int I, int rI>
49+
void sin_cos() {
50+
ap_int<W> a;
51+
auto ap_fixed_SinCos = __spirv_FixedSinCosINTEL<W, rW>(a, S, I, rI);
52+
// CHECK: %{{.*}} = call spir_func i40 @_Z[[#]]__spirv_FixedSinCosINTEL{{.*}}(i31 signext %[[#]], i1 zeroext true, i32 10, i32 12, i32 0, i32 0)
53+
}
54+
55+
template <int W, int rW, bool S, int I, int rI>
56+
void sin_pi() {
57+
ap_int<W> a;
58+
auto ap_fixed_SinPi = __spirv_FixedSinPiINTEL<W, rW>(a, S, I, rI);
59+
// CHECK: %{{.*}} = call spir_func signext i5 @_Z[[#]]__spirv_FixedSinPiINTEL{{.*}}(i60 %[[#]], i1 zeroext false, i32 2, i32 2, i32 0, i32 0)
60+
}
61+
62+
template <int W, int rW, bool S, int I, int rI>
63+
void cos_pi() {
64+
ap_int<W> a;
65+
auto ap_fixed_CosPi = __spirv_FixedCosPiINTEL<W, rW>(a, S, I, rI);
66+
// CHECK: %{{.*}} = call spir_func signext i16 @_Z[[#]]__spirv_FixedCosPiINTEL{{.*}}(i28 signext %[[#]], i1 zeroext false, i32 8, i32 5, i32 0, i32 0)
67+
}
68+
69+
template <int W, int rW, bool S, int I, int rI>
70+
void sin_cos_pi() {
71+
ap_int<W> a;
72+
auto ap_fixed_SinCosPi = __spirv_FixedSinCosPiINTEL<W, rW>(a, S, I, rI);
73+
// CHECK: %{{.*}} = call spir_func signext i10 @_Z[[#]]__spirv_FixedSinCosPiINTEL{{.*}}(i13 signext %[[#]], i1 zeroext false, i32 2, i32 2, i32 0, i32 0)
74+
}
75+
76+
template <int W, int rW, bool S, int I, int rI>
77+
void log() {
78+
ap_int<W> a;
79+
auto ap_fixed_Log = __spirv_FixedLogINTEL<W, rW>(a, S, I, rI);
80+
// CHECK: %{{.*}} = call spir_func i44 @_Z[[#]]__spirv_FixedLogINTEL{{.*}}(i64 %[[#]], i1 zeroext true, i32 24, i32 22, i32 0, i32 0)
81+
}
82+
83+
template <int W, int rW, bool S, int I, int rI>
84+
void exp() {
85+
ap_int<W> a;
86+
auto ap_fixed_Exp = __spirv_FixedExpINTEL<W, rW>(a, S, I, rI);
87+
// CHECK: %{{.*}} = call spir_func i34 @_Z[[#]]__spirv_FixedExpINTEL{{.*}}(i44 %[[#]], i1 zeroext false, i32 20, i32 20, i32 0, i32 0)
88+
}
89+
90+
template <typename name, typename Func>
91+
__attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) {
92+
kernelFunc();
93+
}
94+
95+
int main() {
96+
kernel_single_task<class kernel_function>([]() {
97+
sqrt<13, 5, false, 2, 2>();
98+
recip<3, 8, true, 4, 4>();
99+
rsqrt<11, 10, false, 8, 6>();
100+
sin<17, 11, true, 7, 5>();
101+
cos<35, 28, false, 9, 3>();
102+
sin_cos<31, 20, true, 10, 12>();
103+
sin_pi<60, 5, false, 2, 2>();
104+
cos_pi<28, 16, false, 8, 5>();
105+
sin_cos_pi<13, 5, false, 2, 2>();
106+
log<64, 44, true, 24, 22>();
107+
exp<44, 34, false, 20, 20>();
108+
});
109+
return 0;
110+
}

0 commit comments

Comments
 (0)