How to export the dpi function between c and sv

/proj/common/my_common_pkg.sv


package my_common_pkg;
        import uvm_pkg::*;
        `include "my_globals.svh"
endpackage: my_common_pkg

/proj/common/my_globals.svh


typedef struct {
    string name;
    uint32 addr;
} reg_t;

reg_t reg_arr[$];

import "DPI-C" context function void get_all_reg();

export "DPI-C" function exported_sv_function;

function void exported_sv_function(input reg_t ele);
    reg_arr.push_back(ele);
endfunction : exported_sv_function

and here is my c file: (proj/common/get_all_reg.cpp)
[c]
struct reg_t{
const char* name;
uint32 addr;
};

extern “C” {
void exported_sv_function(reg_t);

void get_all_reg() {
reg_t reg_element;
… // get infomation

exported_sv_function(reg_element);

}
} // extern “C”
[/c]

/proj/test/my_test_pkg.sv


package my_test_pkg;
    import uvm_pkg::*;
    import my_common_pkg::*;

    `include "my_test1.svh"


endpackage : my_test_pkg

and then in my test file (/proj/test/my_test1.svh), I will invoke the get_all_reg() function as shown below.


class my_test1 extends uvm_test;
  ...
  task run_phase(uvm_phase phase);
    super.run_phase(phase);
    phase.raise_objection(this, "raise objection");
    get_all_reg();
    ...
  endtask
endclass


But in the runtime, it will report below error:
Error-[DPI-DXFNF] DPI export function not found
The DPI export function/task ‘exported_sv_function’ called from a user/external C/C++/DPI-C code originated from import DPI function is not defined or visible.

In reply to zz8318:
It would help to show a minimal, complete example. Where are the DPI import/export statements in relation to where the call to get_all_reg()?

In reply to dave_59:

Hi Dave,

I edited my post. Thanks for your advice.

Merry X-mas and Happy new year.

In reply to zz8318:

That’s better, but certainly not minimal or complete. This worked for me:

package my_common_pkg;
   typedef struct {
      string name;
      int addr;
   } reg_t;
   reg_t reg_arr[$];
   import "DPI-C" context function void get_all_reg();
   export "DPI-C" function exported_sv_function;
   function void exported_sv_function(input reg_t ele);
      reg_arr.push_back(ele);
   endfunction : exported_sv_function  
endpackage: my_common_pkg
package my_test_pkg;
   import my_common_pkg::*;
class A;
   task run;
      get_all_reg;
   endtask 
endclass 
endpackage : my_test_pkg
module top;
   import my_test_pkg::*;
   A h=new;
   initial h.run;
endmodule

Note the changes I had to make get the C++ code to compile

extern "C" {
void exported_sv_function(const reg_t*);
 
void get_all_reg() {
    reg_t reg_element;
        // get infomation
 
    exported_SystemVerilog_function(&reg_element);
}
}  // extern "C"

In reply to dave_59:

Hi Dave,

The run task in your code is invoked in the top module. Shall I know the reason ?

In reply to zz8318:

In reply to dave_59:
Hi Dave,
The run task in your code is invoked in the top module. Shall I know the reason ?

I’m giving you a minimal complete example that you can try yourself. You need to do the same, otherwise no one can help you.

In reply to dave_59:

Hi Dave,

I was not able to solve this problem in my side. And I tried another way to implement it but failed at below error. I am not sure if I use the dpi correctly or not. Could you please take a look ?

I don’t use ‘export’ function and what I tried is shown below.

/proj/common/my_globals.svh:


typedef struct {
    string name;
    uint32 addr;
} reg_t;
 
import "DPI-C" context function void get_all_reg2(output reg_t arr[]);

and here is my c file: (proj/common/get_all_reg.cpp)
[c]
struct reg_t{
const char* name;
uint32 addr;
};

extern “C” {
void get_all_reg2(svOpenArrayHandle arr) {

reg_t  reg_element;
reg_t *reg_array;
reg_array = (reg_t*)svGetArrayPtr(arr);

while(...) {
  ...
  reg_array[idx] = reg_element;
  idx++;
}

}
} // extern “C”
[/c]

and then in my test file (/proj/test/my_test2.svh), I will invoke the get_all_reg2() function as shown below.


class my_test2 extends uvm_test;
  ...
  reg_t m_reg_array[1024];      // shall we need to identify 1024 ?
  ...
  task run_phase(uvm_phase phase);
    super.run_phase(phase);
    phase.raise_objection(this, "raise objection");
    get_all_reg2(m_reg_array);
    ...
  endtask
endclass

and I met the segmentation fault…

In reply to zz8318:

Please read carefully what Dave mentioned regarding posting a minimal complete example. It needs to be an complete set of code that will compile for both SV and C++. Posting incomplete code sections with ‘while(…)’ and ‘…’ DOES NOT HELP since they can’t be compiled to determine what the issue is.

Dave posted a complete example that works. Please post a complete example which exhibits the issue you are seeing.

In reply to cgales:

Thanks for your advice. I will take a further investigate and try to figure it out.