LCOV - code coverage report
Current view: top level - src/pw - pw_fpga.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:71c3ab0) Lines: 26.7 % 15 4
Test Date: 2026-07-25 06:35:44 Functions: 28.6 % 7 2

            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              : 
        

Generated by: LCOV version 2.0-1