Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : ! **************************************************************************************************
9 : !> \note
10 : !> This module contains routines necessary to operate on plane waves on INTEL
11 : !> FPGAs using OpenCL. It depends at execution time on the board support
12 : !> packages of the specific FPGA
13 : !> \author Arjun Ramaswami
14 : !> \author Robert Schade
15 : ! **************************************************************************************************
16 :
17 : MODULE pw_fpga
18 : USE ISO_C_BINDING, ONLY: C_CHAR,&
19 : C_DOUBLE_COMPLEX,&
20 : C_FLOAT_COMPLEX,&
21 : C_INT,&
22 : C_NULL_CHAR
23 : USE cp_files, ONLY: get_data_dir
24 : USE kinds, ONLY: dp,&
25 : sp
26 : #include "../base/base_uses.f90"
27 :
28 : IMPLICIT NONE
29 :
30 : PRIVATE
31 :
32 : PUBLIC :: pw_fpga_init, pw_fpga_finalize
33 : PUBLIC :: pw_fpga_init_bitstream
34 : PUBLIC :: pw_fpga_r3dc1d_3d_sp, pw_fpga_c1dr3d_3d_sp
35 : PUBLIC :: pw_fpga_r3dc1d_3d_dp, pw_fpga_c1dr3d_3d_dp
36 :
37 : INTERFACE
38 : ! **************************************************************************************************
39 : !> \brief Initialize FPGA
40 : !> \retval status if the routine failed or not
41 : ! **************************************************************************************************
42 : FUNCTION pw_fpga_initialize() RESULT(stat) &
43 : BIND(C, name="pw_fpga_initialize_")
44 : IMPORT
45 : INTEGER(KIND=C_INT) :: stat
46 : END FUNCTION pw_fpga_initialize
47 :
48 : ! **************************************************************************************************
49 : !> \brief Destroy FPGA
50 : ! **************************************************************************************************
51 : SUBROUTINE pw_fpga_final() &
52 : BIND(C, name="pw_fpga_final_")
53 : END SUBROUTINE pw_fpga_final
54 :
55 : END INTERFACE
56 :
57 : INTERFACE
58 : ! **************************************************************************************************
59 : !> \brief Check whether an fpga bitstream for the given FFT3d size is present & load binary if needed
60 : !> \param data_path - path to the data directory
61 : !> \param npts - fft3d size
62 : !> \return res - true if fft3d size supported
63 : ! **************************************************************************************************
64 : FUNCTION pw_fpga_check_bitstream(data_path, n) RESULT(res) &
65 : BIND(C, name="pw_fpga_check_bitstream_")
66 : IMPORT
67 : CHARACTER(KIND=C_CHAR) :: data_path(*)
68 : INTEGER(KIND=C_INT) :: n(3)
69 : INTEGER(KIND=C_INT) :: res
70 : END FUNCTION pw_fpga_check_bitstream
71 :
72 : END INTERFACE
73 :
74 : INTERFACE
75 : ! **************************************************************************************************
76 : !> \brief single precision FFT3d using FPGA
77 : !> \param dir - direction of FFT3d
78 : !> \param npts - dimensions of FFT3d
79 : !> \param single precision c_in...
80 : ! **************************************************************************************************
81 : SUBROUTINE pw_fpga_fft3d_sp(dir, n, c_in_sp) &
82 : BIND(C, name="pw_fpga_fft3d_sp_")
83 : IMPORT
84 : INTEGER(KIND=C_INT), VALUE :: dir
85 : INTEGER(KIND=C_INT) :: n(3)
86 : COMPLEX(KIND=C_FLOAT_COMPLEX) :: c_in_sp(n(1), n(2), n(3))
87 : END SUBROUTINE pw_fpga_fft3d_sp
88 : END INTERFACE
89 :
90 : INTERFACE
91 : ! **************************************************************************************************
92 : !> \brief double precision FFT3d using FPGA
93 : !> \param dir - direction of FFT3d
94 : !> \param npts - dimensions of FFT3d
95 : !> \param double precision c_in...
96 : ! **************************************************************************************************
97 : SUBROUTINE pw_fpga_fft3d_dp(dir, n, c_in_dp) &
98 : BIND(C, name="pw_fpga_fft3d_dp_")
99 : IMPORT
100 : INTEGER(KIND=C_INT), VALUE :: dir
101 : INTEGER(KIND=C_INT) :: n(3)
102 : COMPLEX(KIND=C_DOUBLE_COMPLEX) :: c_in_dp(n(1), n(2), n(3))
103 : END SUBROUTINE pw_fpga_fft3d_dp
104 : END INTERFACE
105 :
106 : CONTAINS
107 :
108 : ! **************************************************************************************************
109 : !> \brief Allocates resources on the fpga device
110 : ! **************************************************************************************************
111 10486 : SUBROUTINE pw_fpga_init()
112 : #if defined (__PW_FPGA)
113 : INTEGER :: stat
114 :
115 : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_PW)
116 : #error "OFFLOAD and FPGA cannot be configured concurrently! Recompile with -D__NO_OFFLOAD_PW."
117 : CPABORT("OFFLOAD and FPGA cannot be configured concurrently! Recompile with -D__NO_OFFLOAD_PW.")
118 : #endif
119 : stat = pw_fpga_initialize()
120 : IF (stat /= 0) THEN
121 : CPABORT("pw_fpga_init: failed")
122 : END IF
123 : #endif
124 :
125 : #if (__PW_FPGA_SP && !(__PW_FPGA))
126 : #error "Define both __PW_FPGA_SP and __PW_FPGA"
127 : CPABORT("Define both __PW_FPGA_SP and __PW_FPGA")
128 : #endif
129 :
130 10486 : END SUBROUTINE pw_fpga_init
131 :
132 : ! **************************************************************************************************
133 : !> \brief Releases resources on the fpga device
134 : ! **************************************************************************************************
135 10486 : SUBROUTINE pw_fpga_finalize()
136 : #if defined (__PW_FPGA)
137 : CALL pw_fpga_final()
138 : #endif
139 10486 : END SUBROUTINE pw_fpga_finalize
140 :
141 : ! **************************************************************************************************
142 : !> \brief perform an in-place double precision fft3d on the FPGA
143 : !> \param n ...
144 : !> \param c_out ...
145 : ! **************************************************************************************************
146 0 : SUBROUTINE pw_fpga_r3dc1d_3d_dp(n, c_out)
147 : INTEGER, DIMENSION(:), INTENT(IN) :: n
148 : COMPLEX(KIND=dp), INTENT(INOUT) :: c_out(n(1), n(2), n(3))
149 :
150 : #if ! defined (__PW_FPGA)
151 : MARK_USED(c_out)
152 : MARK_USED(n)
153 : #else
154 : INTEGER :: handle3
155 :
156 : CHARACTER(len=*), PARAMETER :: routineX = 'fw_fft_fpga_r3dc1d_dp'
157 :
158 : CALL timeset(routineX, handle3)
159 : CALL pw_fpga_fft3d_dp(+1, n, c_out)
160 : CALL timestop(handle3)
161 :
162 : #endif
163 0 : END SUBROUTINE pw_fpga_r3dc1d_3d_dp
164 :
165 : ! **************************************************************************************************
166 : !> \brief perform an in-place double precision inverse fft3d on the FPGA
167 : !> \param n ...
168 : !> \param c_out ...
169 : ! **************************************************************************************************
170 0 : SUBROUTINE pw_fpga_c1dr3d_3d_dp(n, c_out)
171 : INTEGER, DIMENSION(:), INTENT(IN) :: n
172 : COMPLEX(KIND=dp), INTENT(INOUT) :: c_out(n(1), n(2), n(3))
173 :
174 : #if ! defined (__PW_FPGA)
175 : MARK_USED(c_out)
176 : MARK_USED(n)
177 : #else
178 : INTEGER :: handle3
179 :
180 : CHARACTER(len=*), PARAMETER :: routineX = 'bw_fft_fpga_c1dr3d_dp'
181 :
182 : CALL timeset(routineX, handle3)
183 : CALL pw_fpga_fft3d_dp(-1, n, c_out)
184 : CALL timestop(handle3)
185 :
186 : #endif
187 0 : END SUBROUTINE pw_fpga_c1dr3d_3d_dp
188 :
189 : ! **************************************************************************************************
190 : !> \brief perform an in-place single precision fft3d on the FPGA
191 : !> \param n ...
192 : !> \param c_out ...
193 : ! **************************************************************************************************
194 0 : SUBROUTINE pw_fpga_r3dc1d_3d_sp(n, c_out)
195 : INTEGER, DIMENSION(:), INTENT(IN) :: n
196 : COMPLEX(KIND=dp), INTENT(INOUT) :: c_out(n(1), n(2), n(3))
197 :
198 : #if ! defined (__PW_FPGA)
199 : MARK_USED(c_out)
200 : MARK_USED(n)
201 : #else
202 : COMPLEX, DIMENSION(:, :, :), POINTER :: c_in_sp
203 : INTEGER :: handle3
204 :
205 : CHARACTER(len=*), PARAMETER :: routineX = 'fw_fft_fpga_r3dc1d_sp'
206 :
207 : ALLOCATE (c_in_sp(n(1), n(2), n(3)))
208 : ! pointer to single precision complex array
209 : c_in_sp = CMPLX(c_out, KIND=sp)
210 :
211 : CALL timeset(routineX, handle3)
212 : CALL pw_fpga_fft3d_sp(+1, n, c_in_sp)
213 : CALL timestop(handle3)
214 :
215 : ! typecast sp back to dp
216 : !c_out = CMPLX(real(c_in_sp), 0.0_dp, KIND=dp)
217 : c_out = CMPLX(c_in_sp, KIND=dp)
218 :
219 : DEALLOCATE (c_in_sp)
220 : #endif
221 0 : END SUBROUTINE pw_fpga_r3dc1d_3d_sp
222 :
223 : ! **************************************************************************************************
224 : !> \brief perform an in-place single precision inverse fft3d on the FPGA
225 : !> \param n ...
226 : !> \param c_out ...
227 : ! **************************************************************************************************
228 0 : SUBROUTINE pw_fpga_c1dr3d_3d_sp(n, c_out)
229 : INTEGER, DIMENSION(:), INTENT(IN) :: n
230 : COMPLEX(KIND=dp), INTENT(INOUT) :: c_out(n(1), n(2), n(3))
231 :
232 : #if ! defined (__PW_FPGA)
233 : MARK_USED(c_out)
234 : MARK_USED(n)
235 :
236 : #else
237 : COMPLEX, DIMENSION(:, :, :), POINTER :: c_in_sp
238 : INTEGER :: handle3
239 :
240 : CHARACTER(len=*), PARAMETER :: routineX = 'bw_fft_fpga_c1dr3d_sp'
241 :
242 : ALLOCATE (c_in_sp(n(1), n(2), n(3)))
243 : ! pointer to single precision complex array
244 : c_in_sp = CMPLX(c_out, KIND=sp)
245 :
246 : CALL timeset(routineX, handle3)
247 : CALL pw_fpga_fft3d_sp(-1, n, c_in_sp)
248 : CALL timestop(handle3)
249 :
250 : ! typecast sp back to dp
251 : c_out = CMPLX(c_in_sp, KIND=dp)
252 :
253 : DEALLOCATE (c_in_sp)
254 : #endif
255 0 : END SUBROUTINE pw_fpga_c1dr3d_3d_sp
256 :
257 : ! **************************************************************************************************
258 : !> \brief Invoke the pw_fpga_check_bitstream C function passing the path to the data dir
259 : !> \param n - fft3d size
260 : !> \return ...
261 : !> \retval res - true if fft size found and initialized else false
262 : ! **************************************************************************************************
263 0 : FUNCTION pw_fpga_init_bitstream(n) RESULT(res)
264 : INTEGER, DIMENSION(:), INTENT(IN) :: n
265 : INTEGER :: res
266 :
267 : #if ! defined (__PW_FPGA)
268 0 : res = 0
269 : MARK_USED(n)
270 : MARK_USED(res)
271 : #else
272 : CHARACTER(len=100) :: data_path
273 : INTEGER :: data_path_len
274 :
275 : data_path = TRIM(get_data_dir())//C_NULL_CHAR
276 : data_path_len = LEN_TRIM(data_path)
277 :
278 : res = pw_fpga_check_bitstream(data_path, n)
279 : #endif
280 0 : END FUNCTION pw_fpga_init_bitstream
281 :
282 : END MODULE pw_fpga
283 :
|