Following section lists a complete example test that uses 2-D fixed point SSR FFT L1 module. The header file named top_2d_fft_test.hpp
listed
below provides definition of most of the template parameters and data types used in test and also
the declaration of top level function top_fft2d
that will be synthesized.
#ifndef _TOP_2D_FFT_TEST_H_ #define _TOP_2D_FFT_TEST_H_ #ifndef __SYNTHESIS__ #include <iostream> #endif #include "vt_fft.hpp" #ifndef __SYNTHESIS__ #include <iostream> #endif using namespace xf::dsp::fft; typedef ap_fixed<27, 8> T_innerData; typedef std::complex<T_innerData> T_elemType; const int k_memWidthBits = 512; const int k_memWidth = k_memWidthBits / (sizeof(std::complex<T_innerData>) * 8); const int k_fftKernelRadix = 4; const int k_numOfKernels = k_memWidth / (k_fftKernelRadix); const int k_fftKernelSize = 16; typedef float T_innerFloat; typedef std::complex<T_innerFloat> T_compleFloat; const int k_numRows = k_fftKernelSize; const int k_numCols = k_fftKernelSize; const int k_rowInstanceIDOffset = 40000; const int k_colInstanceIDOffset = 80000; const int k_totalWideSamples = k_fftKernelSize * k_fftKernelSize / k_memWidth; struct FFTParams : ssr_fft_default_params { static const int N = k_fftKernelSize; static const int R = k_fftKernelRadix; static const scaling_mode_enum scaling_mode = SSR_FFT_NO_SCALING; static const transform_direction_enum transform_direction = FORWARD_TRANSFORM; }; struct FFTParams2 : ssr_fft_default_params { static const int N = k_fftKernelSize; static const int R = k_fftKernelRadix; static const scaling_mode_enum scaling_mode = SSR_FFT_NO_SCALING; static const transform_direction_enum transform_direction = FORWARD_TRANSFORM; }; typedef FFTIOTypes<FFTParams, T_elemType>::T_outType T_outType_row; typedef FFTIOTypes<FFTParams2, T_outType_row>::T_outType T_outType; typedef WideTypeDefs<k_memWidth, T_elemType>::WideIFType MemWideIFTypeIn; typedef WideTypeDefs<k_memWidth, T_elemType>::WideIFStreamType MemWideIFStreamTypeIn; typedef WideTypeDefs<k_memWidth, T_outType>::WideIFType MemWideIFTypeOut; typedef WideTypeDefs<k_memWidth, T_outType>::WideIFStreamType MemWideIFStreamTypeOut; void top_fft2d(MemWideIFStreamTypeIn& p_inStream, MemWideIFStreamTypeOut& p_outStream); #endif
Following .cpp
file named top_2d_fft_test.cpp
defines top level function which essentially calls fft2d
from Vitis FFT library.
#include "top_2d_fft_test.hpp" void top_fft2d(MemWideIFStreamTypeIn& p_inStream, MemWideIFStreamTypeOut& p_outStream) { #ifdef _DEBUG_TYPES T_outType_row T_outType_row_temp; T_outType T_outType_temp; MemWideIFTypeIn MemWideIFTypeIn_temp; MemWideIFTypeOut MemWideIFTypeOut_temp; #endif #pragma HLS INLINE #pragma HLS DATA_PACK variable = p_inStream #pragma HLS DATA_PACK variable = p_outStream #pragma HLS interface ap_ctrl_none port = return #ifndef __SYNTHESIS__ std::cout << "================================================================================" << std::endl; std::cout << "-------------------Calling 2D SSR FFT Kernel with Parameters--------------------" << std::endl; std::cout << "================================================================================" << std::endl; std::cout << " The Main Memory Width (no. complex<ap_fixed>) : " << k_memWidth << std::endl; std::cout << " The Size of 1D Row Kernel : " << FFTParams::N << std::endl; std::cout << " The SSR for 1D Row Kernel : " << FFTParams::R << std::endl; std::cout << " The Transform Direction for Row Kernel : " << ((FFTParams::transform_direction == FORWARD_TRANSFORM) ? "Forward" : "Reverse"); std::cout << std::endl; std::cout << " The Size of 1D Column Kernel : " << FFTParams2::N << std::endl; std::cout << " The SSR for 1D Row Kernel : " << FFTParams2::R << std::endl; std::cout << " The Transform Direction for Row Kernel : " << ((FFTParams2::transform_direction == FORWARD_TRANSFORM) ? "Forward" : "Reverse"); std::cout << std::endl; std::cout << " The Row Instance ID Offset : " << k_rowInstanceIDOffset << std::endl; std::cout << " The Column Instance ID Offset : " << k_colInstanceIDOffset << std::endl; std::cout << " Number of 1D Kernels Used Row/Col wise : " << k_numOfKernels << std::endl; std::cout << " The Total Number of 1D Kernels Used(row+col) : " << 2 * k_numOfKernels << std::endl; std::cout << "================================================================================" << std::endl; #endif fft2d<k_memWidth, k_fftKernelSize, k_fftKernelSize, k_numOfKernels, FFTParams, FFTParams2, k_rowInstanceIDOffset, k_colInstanceIDOffset, T_elemType>(p_inStream, p_outStream); }
The main
function is defined as follows which runs an impulse test:
#define TEST_2D_FFT_ #ifdef TEST_2D_FFT_ #ifndef __SYNTHESIS__ #define _DEBUG_TYPES #endif #include <math.h> #include <string> #include <assert.h> #include <stdio.h> #include "top_2d_fft_test.hpp" #include "mVerificationUtlityFunctions.hpp" #include "vitis_fft/hls_ssr_fft_2d_modeling_utilities.hpp" #include "vt_fft.hpp" int main(int argc, char** argv) { // 2d input matrix T_elemType l_inMat[k_fftKernelSize][k_fftKernelSize]; T_outType l_outMat[k_fftKernelSize][k_fftKernelSize]; T_outType l_data2d_golden[k_fftKernelSize][k_fftKernelSize]; // init input matrix with real part only impulse for (int r = 0; r < k_fftKernelSize; ++r) { for (int c = 0; c < k_fftKernelSize; ++c) { if (r == 0 && c == 0) l_inMat[r][c] = T_compleFloat(1, 0); else l_inMat[r][c] = T_compleFloat(0, 0); } } // Wide Stream for reading and streaming a 2-d matrix MemWideIFStreamTypeIn l_matToStream("matrixToStreaming"); MemWideIFStreamTypeOut fftOutputStream("fftOutputStream"); // Pass same data stream multiple times to measure the II correctly for (int runs = 0; runs < 5; ++runs) { stream2DMatrix<k_fftKernelSize, k_fftKernelSize, k_memWidth, T_elemType, MemWideIFTypeIn>(l_inMat, l_matToStream); top_fft2d(l_matToStream, fftOutputStream); printMatStream<k_fftKernelSize, k_fftKernelSize, k_memWidth, MemWideIFTypeOut>( fftOutputStream, "2D SSR FFT Output Natural Order..."); streamToMatrix<k_fftKernelSize, k_fftKernelSize, k_memWidth, T_outType>(fftOutputStream, l_outMat); } // runs loop T_outType golden_result = T_elemType(1, 0); for (int r = 0; r < k_fftKernelSize; ++r) { for (int c = 0; c < k_fftKernelSize; ++c) { if (golden_result != l_outMat[r][c]) return 1; } } std::cout << "================================================================" << std::endl; std::cout << "---------------------Impulse test Passed Successfully." << std::endl; std::cout << "================================================================" << std::endl; return 0; } #endif