Problems with the use of structure with real array in it in DPI-C

Is there any issue with using following structure in the DPI-C function input ?

typedef struct {
  real i;
  real k;
  real l;
  real m;
  real j;
  real toggle;
  real real_in[4];
  real imag_in[4];
} struct0_T;

c-code

void increment(const struct0_T *a, const double b[4], struct1_T *res,
               double re_out_real[4], double re_out_imag[4])
{
  res->ij = a->i * b[0] + a->j * b[1];
  res->kl = a->k * b[2] + a->l * b[3];
  if (a->toggle == 0.0) {
    re_out_real[0] = a->real_in[0] * 5.0;
    re_out_imag[0] = a->imag_in[0] * 5.0;
    re_out_real[1] = a->real_in[1] * 5.0;
    re_out_imag[1] = a->imag_in[1] * 5.0;
    re_out_real[2] = a->real_in[2] * 5.0;
    re_out_imag[2] = a->imag_in[2] * 5.0;
    re_out_real[3] = a->real_in[3] * 5.0;
    re_out_imag[3] = a->imag_in[3] * 5.0;
  } else {
    re_out_real[0] = a->real_in[0] * 4.0;
    re_out_imag[0] = a->imag_in[0] * 4.0;
    re_out_real[1] = a->real_in[1] * 4.0;
    re_out_imag[1] = a->imag_in[1] * 4.0;
    re_out_real[2] = a->real_in[2] * 4.0;
    re_out_imag[2] = a->imag_in[2] * 4.0;
    re_out_real[3] = a->real_in[3] * 4.0;
    re_out_imag[3] = a->imag_in[3] * 4.0;
  }
  res->real_out[0] = re_out_real[0];
  res->imag_out[0] = re_out_imag[0];
  res->real_out[1] = re_out_real[1];
  res->imag_out[1] = re_out_imag[1];
  res->real_out[2] = re_out_real[2];
  res->imag_out[2] = re_out_imag[2];
  res->real_out[3] = re_out_real[3];
  res->imag_out[3] = re_out_imag[3];
  printf("real _in = %f \n", a->real_in[0]);
  fflush(stdout);
  printf("imag _in = %f \n", a->imag_in[0]);
  fflush(stdout);
  printf("real _in = %f \n", a->real_in[1]);
  fflush(stdout);
  printf("imag _in = %f \n", a->imag_in[1]);
  fflush(stdout);
  printf("real _in = %f \n", a->real_in[2]);
  fflush(stdout);
  printf("imag _in = %f \n", a->imag_in[2]);
  fflush(stdout);
  printf("real _in = %f \n", a->real_in[3]);
  fflush(stdout);
  printf("imag _in = %f \n", a->imag_in[3]);
  fflush(stdout);
  printf("real _out = %f \n", re_out_real[0]);
  fflush(stdout);
  printf("imag _out = %f \n", re_out_imag[0]);
  fflush(stdout);
  printf("real _out = %f \n", re_out_real[1]);
  fflush(stdout);
  printf("imag _out = %f \n", re_out_imag[1]);
  fflush(stdout);
  printf("real _out = %f \n", re_out_real[2]);
  fflush(stdout);
  printf("imag _out = %f \n", re_out_imag[2]);
  fflush(stdout);
  printf("real _out = %f \n", re_out_real[3]);
  fflush(stdout);
  printf("imag _out = %f \n", re_out_imag[3]);
  fflush(stdout);
}

when this routine is called in SV, it somehow doesnt read the 1st elements of the real_in, imag_in members of the struct. values appear to be shifted by 2 indices. 0th and 1st elments of these arrays read 0.
if the type of these arrays is “int” , then the values are read correctly on the c-side of the interface.

Any comments. Thanks in advance.

In reply to venhari:

It would help to see what your SystemVerilog code looks like. You only showed the struct0_T type, not the struct1_T type. I collapsed them onto the same type and this worked for me

SystemVerilog code:

typedef struct {
   real i;
   real k;
   real l;
   real m;
   real j;
  real toggle;
  real Real[4];
  real Imag[4];
} struct0_T; 

module top;
   import "DPI-C" function void increment(
				  input struct0_T a, real b[4],
				  output struct0_T res,
				  real re_out_real[4],
				  real re_out_imag[4]
				  );
   struct0_T A 	= '{1.1, 2.2, 3.3,4.4, 5.5, 6.6,  {1.5,1.6,1.7,1.8}, {2.5,2.6,2.7,2.8} };
   struct0_T RES;
   real B[4],oR[4],oI[4];
   
   initial begin
      increment(A,B,RES,oR,oI);
      $display("%p",RES);
      end
endmodule

C code:

#include "struct.h"
#include < stdio.h >

void increment(const struct0_T *a, const double b[4], struct0_T *res,
               double re_out_real[4], double re_out_imag[4])
{
  res->i = a->i * b[0] + a->j * b[1];
  res->k = a->k * b[2] + a->l * b[3];
  if (a->toggle == 0.0) {
    re_out_real[0] = a->Real[0] * 5.0;
    re_out_imag[0] = a->Imag[0] * 5.0;
    re_out_real[1] = a->Real[1] * 5.0;
    re_out_imag[1] = a->Imag[1] * 5.0;
    re_out_real[2] = a->Real[2] * 5.0;
    re_out_imag[2] = a->Imag[2] * 5.0;
    re_out_real[3] = a->Real[3] * 5.0;
    re_out_imag[3] = a->Imag[3] * 5.0;
  } else {
    re_out_real[0] = a->Real[0] * 4.0;
    re_out_imag[0] = a->Imag[0] * 4.0;
    re_out_real[1] = a->Real[1] * 4.0;
    re_out_imag[1] = a->Imag[1] * 4.0;
    re_out_real[2] = a->Real[2] * 4.0;
    re_out_imag[2] = a->Imag[2] * 4.0;
    re_out_real[3] = a->Real[3] * 4.0;
    re_out_imag[3] = a->Imag[3] * 4.0;
  }
  res->Real[0] = re_out_real[0];
  res->Imag[0] = re_out_imag[0];
  res->Real[1] = re_out_real[1];
  res->Imag[1] = re_out_imag[1];
  res->Real[2] = re_out_real[2];
  res->Imag[2] = re_out_imag[2];
  res->Real[3] = re_out_real[3];
  res->Imag[3] = re_out_imag[3];
  printf("real _in = %f \n", a->Real[0]);
  fflush(stdout);
  printf("imag _in = %f \n", a->Imag[0]);
  fflush(stdout);
  printf("real _in = %f \n", a->Real[1]);
  fflush(stdout);
  printf("imag _in = %f \n", a->Imag[1]);
  fflush(stdout);
  printf("real _in = %f \n", a->Real[2]);
  fflush(stdout);
  printf("imag _in = %f \n", a->Imag[2]);
  fflush(stdout);
  printf("real _in = %f \n", a->Real[3]);
  fflush(stdout);
  printf("imag _in = %f \n", a->Imag[3]);
  fflush(stdout);
  printf("real _out = %f \n", re_out_real[0]);
  fflush(stdout);
  printf("imag _out = %f \n", re_out_imag[0]);
  fflush(stdout);
  printf("real _out = %f \n", re_out_real[1]);
  fflush(stdout);
  printf("imag _out = %f \n", re_out_imag[1]);
  fflush(stdout);
  printf("real _out = %f \n", re_out_real[2]);
  fflush(stdout);
  printf("imag _out = %f \n", re_out_imag[2]);
  fflush(stdout);
  printf("real _out = %f \n", re_out_real[3]);
  fflush(stdout);
  printf("imag _out = %f \n", re_out_imag[3]);
  fflush(stdout);
}

In reply to dave_59:
my apology for not adding the sv code earlier.




typedef struct {
  real i;
  real k;
  real l;
  real m;
  real j;
  real toggle;
  real real_in[4];
  real imag_in[4];
} struct0_T;

typedef struct {
  real ij;
  real kl;
  real real_out[4];
  real imag_out[4];
} 
module top;
    //import packages
    import uvm_pkg::*;
   
    import "DPI-C" function void increment(input struct0_T inpt, input real sample[4], output struct1_T outp , real re[4], real im[4]);
    
    struct0_T test_i;
    struct1_T test_o; 
    real add_arr[4];
    real re[4];
    real im[4]; 

    initial begin 
      
        test_i.i = 1;
        test_i.j = 2;
        test_i.k = 3;
        test_i.l = 4;
        test_i.toggle = 0.0; 
        add_arr = { 1,2,4,5};
       
        test_i.real_in = '{ 0 , 2, 4 ,6};
        test_i.imag_in = '{ 1 , 3, 5 ,7};

        increment(test_i, add_arr , test_o, re, im);
        $display("DPI_RES : %f", test_o.ij);
        $display("DPI_RES : %f", test_o.kl);
        for (int i =0 ; i < 4; i++) begin 
        $display("DPI_RES real = %f in  = %f  %f ", test_o.real_out[i],test_i.real_in[i] , re[i]);
        $display("DPI_RES imag = %f in  = %f  %f", test_o.imag_out[i], test_i.imag_in[i] , im[i]);
        end 


    end 

    



endmodule




Output observed is :

==============================
real _in = 0.000000                                                                                                                                                                                                                                                           
imag _in = 6.000000                                                                                                                                                                                                                                                           
real _in = 0.000000                                                                                                                                                                                                                                                           
imag _in = 1.000000                                                                                                                                                                                                                                                           real _in = 2.000000                                                                                                                                                                                                                                                           imag _in = 3.000000                                                                                                                                                                                                                                                           real _in = 4.000000                                                                                                                                                                                                                                                           imag _in = 5.000000                                                                                                                                                                                                                                                           real _out = 0.000000                                                                                                                                                                                                                                                          imag _out = 24.000000                                                                                                                                                                                                                                                         real _out = 0.000000                                                                                                                                                                                                                                                          imag _out = 4.000000                                                                                                                                                                                                                                                          real _out = 8.000000                                                                                                                                                                                                                                                          imag _out = 12.000000                                                                                                                                                                                                                                                         real _out = 16.000000                                                                                                                                                                                                                                                         imag _out = 20.000000                                                                                                                                                                                                                                                         
DPI_RES : 7.000000                                                                                                                                                                                                                                                          DPI_RES : 16.000000                                                                                                                                                                                                                                                         DPI_RES real = 0.000000 in  = 0.000000  0.000000                                                                                                                                                                                                                            DPI_RES imag = 24.000000 in  = 1.000000  24.000000                                                                                                                                                                                                                          DPI_RES real = 0.000000 in  = 2.000000  0.000000                                                                                                                                                                                                                            DPI_RES imag = 4.000000 in  = 3.000000  4.000000                                                                                                                                                                                                                            DPI_RES real = 8.000000 in  = 4.000000  8.000000                                                                                                                                                                                                                            DPI_RES imag = 12.000000 in  = 5.000000  12.000000                                                                                                                                                                                                                          DPI_RES real = 16.000000 in  = 6.000000  16.000000                                                                                                                                                                                                                          DPI_RES imag = 20.000000 in  = 7.000000  20.000000

In reply to venhari:

Hi Dave,

I realized my mistake. I have an additional member “m” in the SV structure compared to C structure for “struct0_T” type. This is causing the error.

Thank you for the help. I am just wondering why there was no error when I tried to pass a different type of structure in my code. Doesnt it check the type compatibility, when we pass the pointers of structure?

In reply to venhari:

DPI C code gets compiled independently of your SystemVerilog code. Some tools, like Questa, can generate a DPI C header file based on your SystemVerilog import/export statements. Then you can include that file when compiling your C code. That gives you the type compatibility checks you want at compile time. Check your tool’s user manual for DPI header file generation.

In reply to dave_59:

Hi Dave,
thanks for the suggestion. I went through this section on Questa user manual. However, in mycase, I directly get a shared object file along with the function prototype info. That’s the reason I could not use the header generation feature of questa. I will be more careful from now on at the interface definitions.
Appreciate your time in helping me.

Thanks.