Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2024 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 8570 : 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) &
121 : CPABORT("pw_fpga_init: failed")
122 : #endif
123 :
124 : #if (__PW_FPGA_SP && !(__PW_FPGA))
125 : #error "Define both __PW_FPGA_SP and __PW_FPGA"
126 : CPABORT("Define both __PW_FPGA_SP and __PW_FPGA")
127 : #endif
128 :
129 8570 : END SUBROUTINE pw_fpga_init
130 :
131 : ! **************************************************************************************************
132 : !> \brief Releases resources on the fpga device
133 : ! **************************************************************************************************
134 8570 : SUBROUTINE pw_fpga_finalize()
135 : #if defined (__PW_FPGA)
136 : CALL pw_fpga_final()
137 : #endif
138 8570 : END SUBROUTINE pw_fpga_finalize
139 :
140 : ! **************************************************************************************************
141 : !> \brief perform an in-place double precision fft3d on the FPGA
142 : !> \param n ...
143 : !> \param c_out ...
144 : ! **************************************************************************************************
145 0 : SUBROUTINE pw_fpga_r3dc1d_3d_dp(n, c_out)
146 : INTEGER, DIMENSION(:), INTENT(IN) :: n
147 : COMPLEX(KIND=dp), INTENT(INOUT) :: c_out(n(1), n(2), n(3))
148 :
149 : #if ! defined (__PW_FPGA)
150 : MARK_USED(c_out)
151 : MARK_USED(n)
152 : #else
153 : INTEGER :: handle3
154 :
155 : CHARACTER(len=*), PARAMETER :: routineX = 'fw_fft_fpga_r3dc1d_dp'
156 :
157 : CALL timeset(routineX, handle3)
158 : CALL pw_fpga_fft3d_dp(+1, n, c_out)
159 : CALL timestop(handle3)
160 :
161 : #endif
162 0 : END SUBROUTINE
163 :
164 : ! **************************************************************************************************
165 : !> \brief perform an in-place double precision inverse fft3d on the FPGA
166 : !> \param n ...
167 : !> \param c_out ...
168 : ! **************************************************************************************************
169 0 : SUBROUTINE pw_fpga_c1dr3d_3d_dp(n, c_out)
170 : INTEGER, DIMENSION(:), INTENT(IN) :: n
171 : COMPLEX(KIND=dp), INTENT(INOUT) :: c_out(n(1), n(2), n(3))
172 :
173 : #if ! defined (__PW_FPGA)
174 : MARK_USED(c_out)
175 : MARK_USED(n)
176 : #else
177 : INTEGER :: handle3
178 :
179 : CHARACTER(len=*), PARAMETER :: routineX = 'bw_fft_fpga_c1dr3d_dp'
180 :
181 : CALL timeset(routineX, handle3)
182 : CALL pw_fpga_fft3d_dp(-1, n, c_out)
183 : CALL timestop(handle3)
184 :
185 : #endif
186 0 : END SUBROUTINE
187 :
188 : ! **************************************************************************************************
189 : !> \brief perform an in-place single precision fft3d on the FPGA
190 : !> \param n ...
191 : !> \param c_out ...
192 : ! **************************************************************************************************
193 0 : SUBROUTINE pw_fpga_r3dc1d_3d_sp(n, c_out)
194 : INTEGER, DIMENSION(:), INTENT(IN) :: n
195 : COMPLEX(KIND=dp), INTENT(INOUT) :: c_out(n(1), n(2), n(3))
196 :
197 : #if ! defined (__PW_FPGA)
198 : MARK_USED(c_out)
199 : MARK_USED(n)
200 : #else
201 : COMPLEX, DIMENSION(:, :, :), POINTER :: c_in_sp
202 : INTEGER :: handle3
203 :
204 : CHARACTER(len=*), PARAMETER :: routineX = 'fw_fft_fpga_r3dc1d_sp'
205 :
206 : ALLOCATE (c_in_sp(n(1), n(2), n(3)))
207 : ! pointer to single precision complex array
208 : c_in_sp = CMPLX(c_out, KIND=sp)
209 :
210 : CALL timeset(routineX, handle3)
211 : CALL pw_fpga_fft3d_sp(+1, n, c_in_sp)
212 : CALL timestop(handle3)
213 :
214 : ! typecast sp back to dp
215 : !c_out = CMPLX(real(c_in_sp), 0.0_dp, KIND=dp)
216 : c_out = CMPLX(c_in_sp, KIND=dp)
217 :
218 : DEALLOCATE (c_in_sp)
219 : #endif
220 0 : END SUBROUTINE
221 :
222 : ! **************************************************************************************************
223 : !> \brief perform an in-place single precision inverse fft3d on the FPGA
224 : !> \param n ...
225 : !> \param c_out ...
226 : ! **************************************************************************************************
227 0 : SUBROUTINE pw_fpga_c1dr3d_3d_sp(n, c_out)
228 : INTEGER, DIMENSION(:), INTENT(IN) :: n
229 : COMPLEX(KIND=dp), INTENT(INOUT) :: c_out(n(1), n(2), n(3))
230 :
231 : #if ! defined (__PW_FPGA)
232 : MARK_USED(c_out)
233 : MARK_USED(n)
234 :
235 : #else
236 : COMPLEX, DIMENSION(:, :, :), POINTER :: c_in_sp
237 : INTEGER :: handle3
238 :
239 : CHARACTER(len=*), PARAMETER :: routineX = 'bw_fft_fpga_c1dr3d_sp'
240 :
241 : ALLOCATE (c_in_sp(n(1), n(2), n(3)))
242 : ! pointer to single precision complex array
243 : c_in_sp = CMPLX(c_out, KIND=sp)
244 :
245 : CALL timeset(routineX, handle3)
246 : CALL pw_fpga_fft3d_sp(-1, n, c_in_sp)
247 : CALL timestop(handle3)
248 :
249 : ! typecast sp back to dp
250 : c_out = CMPLX(c_in_sp, KIND=dp)
251 :
252 : DEALLOCATE (c_in_sp)
253 : #endif
254 0 : END SUBROUTINE
255 :
256 : ! **************************************************************************************************
257 : !> \brief Invoke the pw_fpga_check_bitstream C function passing the path to the data dir
258 : !> \param n - fft3d size
259 : !> \return ...
260 : !> \retval res - true if fft size found and initialized else false
261 : ! **************************************************************************************************
262 0 : FUNCTION pw_fpga_init_bitstream(n) RESULT(res)
263 : INTEGER, DIMENSION(:), INTENT(IN) :: n
264 : INTEGER :: res
265 :
266 : #if ! defined (__PW_FPGA)
267 0 : res = 0
268 : MARK_USED(n)
269 : MARK_USED(res)
270 : #else
271 : CHARACTER(len=100) :: data_path
272 : INTEGER :: data_path_len
273 :
274 : data_path = TRIM(get_data_dir())//C_NULL_CHAR
275 : data_path_len = LEN_TRIM(data_path)
276 :
277 : res = pw_fpga_check_bitstream(data_path, n)
278 : #endif
279 0 : END FUNCTION
280 :
281 : END MODULE pw_fpga
282 :
|