system-verilogmodelsimvivadocadencesystem-verilog-dpi

Passing C structs through SystemVerilog DPI-C layer


SystemVerilog LRM has some examples that show how to pass structs in SystemVerilog to\from C through DPI-C layer. However when I try my own example it seems to not work at all in Incisive or Vivado simulator (it does work in ModelSim). I wanted to know if I am doing something wrong, or if it is an issue with the Simulators. My example is as follow:

#include <stdio.h>

typedef struct {
               char f1;
               int f2;
} s1;

void SimpleFcn(const s1 * in,s1 * out){
    printf("In the C function the struct in has f1: %d\n",in->f1);
    printf("In the C function the struct in has f2: %d\n",in->f2);
    out->f1=!(in->f1);
    out->f2=in->f2+1;    
}

I compile the above code into a shared library:

gcc -c -fPIC -Wall -ansi -pedantic -Wno-long-long -fwrapv -O0 dpi_top.c -o dpi_top.o
gcc -shared -lm dpi_top.o -o dpi_top.so

And the SystemVerilog code:

`timescale 1ns / 1ns
typedef struct {
               bit f1;
               int f2;
               } s1;

import "DPI-C" function void SimpleFcn(input s1 in,output s1 out);

module top();
  s1 in,out;
  initial
    begin    
    in.f1=1'b0;  
    in.f2 = 400;
    $display("The input struct in SV has f1: %h and f2:%d",in.f1,in.f2);
    SimpleFcn(in,out);
    $display("The output struct in SV has f1: %h and f2:%d",out.f1,out.f2);
 end

endmodule 

In Incisive I run it using irun:

irun -sv_lib ./dpi_top.so -sv ./top.sv

But it SegV's.

In Vivado I run it using

xvlog -sv ./top.sv 
xelab top -sv_root ./ -sv_lib dpi_top.so -R

It runs fine until it exits simulation, then there is a memory corruption:

Vivado Simulator 2017.4
Time resolution is 1 ns
run -all
The input struct in SV has f1: 0 and f2:        400
In the C function the struct in has f1: 0
In the C function the struct in has f2: 400
The output struct in SV has f1: 1 and f2:        401
exit
*** Error in `xsim.dir/work.top/xsimk': double free or corruption (!prev): 0x00000000009da2c0 ***

Solution

  • You were lucky that this worked in Modelsim. Your SystemVerilog prototype does not match your C prototype. You have f1 as a byte in C and bit in SystemVerilog.

    Modelsim/Questa has a -dpiheader switch that produces a C header file that you can #include into your dpi_top.c file. That way you get a compiler error when the prototypes don't match instead of an unpredictable run-time error. This is the C prototype for your SV code.

    typedef struct {
        svBit f1;
        int f2;
    }  s1;
    
    void SimpleFcn(
        const s1* in,
        s1* out);
    

    But I would recommend sticking with C compatible types in SystemVerilog.