Integrating fftw C function calls inside system verilog code

2.4k Views Asked by At

I have installed fftw C library succefully on my linux system. Here is more info about fftw c => http://www.fftw.org/ I have a sample C code which can call fftw C functions successfully. Below is a C ccode and command to run the C code: Code:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#include <fftw3.h> 

int main(void)
{
    double FFT_in[] = {0.1, 0.6, 0.1, 0.4, 0.5, 0, 0.8, 0.7, 0.8, 0.6, 0.1,0};
    double *IFFT_out;
    int i,size = 12;

    fftw_complex *middle;

    fftw_plan fft;
    fftw_plan ifft;
    middle = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*size);
    IFFT_out = (double *) malloc(size*sizeof(double));

    fft = fftw_plan_dft_r2c_1d(size, FFT_in, middle, FFTW_ESTIMATE);  //Setup fftw plan for fft (real 1D data)
    ifft = fftw_plan_dft_c2r_1d(size, middle, IFFT_out, FFTW_ESTIMATE);   //Setup fftw plan for ifft

    fftw_execute(fft);
    fftw_execute(ifft);

    printf("Input:    \tFFT_coefficient[i][0]      \tFFT_coefficient[i][1]   \tRecovered Output:\n");

    for(i=0;i<size;i++)
        printf("%f\t%f\t\t\t%f\t\t\t%f\n",(FFT_in[i]),middle[i][0],middle[i][1],IFFT_out[i]/size);

    fftw_destroy_plan(fft);
    fftw_destroy_plan(ifft);
    fftw_free(middle);
    free(IFFT_out);

    return 0;
}

I can run this code succesfully with below gcc command: gcc -g -Wall -I/home/usr/fftw/local/include -L/home/usr/fftw/local/lib fftw_test.c -lfftw3 -lm -o fftw_test

Now I want to call this function inside system verilog using DPI method. Before I show my issue, below is a sample DPI-C/systemverilog testcase which I could run successfully: C:code

#include <stdio.h>
#include <stdlib.h>
#include "svdpi.h"

int add(x,y)
{
    int z;
    z=x+y;
    printf("This is from C:%d+%d=%d\n",x,y,z);
    return z;
}

Calling above C function from system verilog using DPI:

module top;
import "DPI-C" function int add(int a, int b);
int a,b,j;

initial begin
    $display("Entering in SystemVerilog Initial Block\n");
    #20
     a=20;b=10;
    j = add(a,b);
    $display("This is from System Verilog:Value of J=%d",j);
    $display("Exiting from SystemVerilog Initial Block");
    #5 $finish;

end

endmodule

and finally I could run this successfully with irun command irun -f run.f where run.f contains following commands:

# Compile the SystemVerilog files
basicadd.sv 
-access +rwc
# Generate a header file called _sv_export.h
-dpiheader _sv_export.h
# Delay compilation of testexport.c until after elaboration
-cpost add.c -end
# Redirect output of ncsc_run to a log file called ncsc_run.log
-log_ncsc_run ncsc_run.log

Now my real issue is When I try to link fftw C with system verilog, I am not able to run it. Below is my C code, which is pretty similar to very first C code I posted: C code:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#include <fftw3.h>
#include "svdpi.h" 

void fftw_test_DPI(double FFT_in[],int size)
{

    double *IFFT_out;
    int i;

    fftw_complex *middle;

    fftw_plan fft;
    fftw_plan ifft;
    middle = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*size);
    IFFT_out = (double *) malloc(size*sizeof(double));

    fft = fftw_plan_dft_r2c_1d(size, FFT_in, middle, FFTW_ESTIMATE);  //Setup fftw plan for fft (real 1D data)
    ifft = fftw_plan_dft_c2r_1d(size, middle, IFFT_out, FFTW_ESTIMATE);   //Setup fftw plan for ifft

    fftw_execute(fft);
    fftw_execute(ifft);

    printf("Input:    \tFFT_coefficient[i][0]      \tFFT_coefficient[i][1]   \tRecovered Output:\n");

    for(i=0;i<size;i++)
        printf("%f\t%f\t\t\t%f\t\t\t%f\n",FFT_in[i],middle[i][0],middle[i][1],IFFT_out[i]/size);

    fftw_destroy_plan(fft);
    fftw_destroy_plan(ifft);
    fftw_free(middle);
    free(IFFT_out);

    //return IFFT_out;
}

Here is my system verilog, where I call above C function:

module top;
import "DPI-C" function void fftw_test_DPI(real FFT_in[0:11], int size);
real j [0:11];
integer i,size;
real FFT_in [0:11]; 

initial begin
    size = 12;
    FFT_in[0] = 0.1;
     FFT_in[1] = 0.6;
     FFT_in[2] = 0.1;
     FFT_in[3] = 0.4;
     FFT_in[4] = 0.5;
     FFT_in[5] = 0.0;
     FFT_in[6] = 0.8;
     FFT_in[7] = 0.7;
     FFT_in[8] = 0.8;
     FFT_in[9] = 0.6;
     FFT_in[10] = 0.1;
     FFT_in[11] = 0.0;

    $display("Entering in SystemVerilog Initial Block\n");
    #20
     fftw_test_DPI(FFT_in,size);

    $display("Printing recovered output from system verilog\n"); 
    //for(i=0;i<size;i++)
        //$display("%f\t\n",(j[i])/size);

    $display("Exiting from SystemVerilog Initial Block");
    #5 $finish;

end

endmodule

And finally I tried it running several ways, I will mentioned couple of ways I tried: 1st method:

irun -f run_fftw.f where run_fftw.f contains:
# Compile the SystemVerilog files
fftw_test.sv 
-access +rwc
# Generate a header file called _sv_export.h
-dpiheader _sv_export.h
# Delay compilation of fftw_test.c until after elaboration
-cpost fftw_test_DPI.c -end
-I/home/usr/fftw/local/include -L/home/usr/fftw/local/lib fftw_test_DPI.c -lfftw3 -lm 
# Redirect output of ncsc_run to a log file called ncsc_run.log
-log_ncsc_run ncsc_run.log

but this results in below error: building library run.so ld: /home/usr/fftw/local/lib/libfftw3.a(mapflags.o): relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC /home/usr/fftw/local/lib/libfftw3.a: could not read symbols: Bad value collect2: ld returned 1 exit status make: * [/home/usr/DPI/./INCA_libs/irun.lnx8664.12.20.nc/librun.so] Error 1 ncsc_run: *E,TBBLDF: Failed to build test library /home/usr/DPI/./INCA_libs/irun.lnx8664.12.20.nc/librun.so

2nd method: 1.gcc -fPIC -O2 -c -g -I/home/ss69/fftw/local/include -I. -L/home/usr/fftw/local/lib -L. -o fftw_test_DPI.o fftw_test_DPI.c -lfftw3 -lm

2.gcc -shared -o libdpi.so fftw_test_DPI.o

3.irun -64bit -sv_lib libdpi.so fftw_test.sv

This results in below error: Loading snapshot worklib.top:sv .................... Done ncsim> run Entering in SystemVerilog Initial Block

ncsim: symbol lookup error: ./libdpi.so: undefined symbol: fftw_malloc

I know my post is kind of difficult to follow, but I would highly appreciate any help.

2

There are 2 best solutions below

0
On

This is a good description and summary of the problem that we discussed earlier. I do not usually work on a *nix system, so I cannot suggest any specific details. What I will point out is that approaching a problem like this in steps is usually a good method.

Your first step of have the fft code called directly from main() is good. However, I did not see a step where (NOT USING SystemVerilog or ncsim) you compiled the fft code into a library and then called that code from main().

It would seem that getting the code to be stored in a separate lib and called from main() is a necessary step. After you have that working, then you should be able to include the fft lib in the SystemVerilog stuff without having to compile the fft routine at the same time?

0
On

You might need to export or setenv LD_LIBRARY_PATH ${LD_LIBRARY_PATH}:/home/usr/fftw/local/lib:.. Unless your libdpi.so is linked with static FFTW library, otherwise, your code will need to load the dynamic version of the FFTW library (libfftw.so?) because you are using fftw_* APIs.