読者です 読者をやめる 読者になる 読者になる

LSI Jiu-Jitsu

半導体とブラジリアン柔術

g++でDPI-C向けライブラリを作成

Eda

g++でコンパイルしたライブラリをSystemVerilogからDPI-Cを通してコールしたところvcsがエラーを吐き出しました。

Error-[DPI-DIFNF] DPI import function not found
**********.sv, **
 The definition of DPI import function/task 'Convert' does not exist.
 Please check the stated DPI import function/task is defined, and its
 definition is either passed in a source file at compile-time, or provided in
 a shared library specified using the LRM Annex-J options at run-time.

どうやらそんな関数(Convert)が見つからないよと言っているようです。

試しにgccコンパイルして問題なくコールできているライブラリをg++でコンパイルし直してみたところ、やはり上記のようなエラーが発生しました。

 

調べてみると、どうやらg++でコンパイルすると名前修飾の影響で関数名が変わってしまうようです。

nmでシンボルリストを見てみると

$ nm refc.so
.............
00000000000093ea T _Z13ConvertiiiiiPviiiiiS_S_iiS_
.............

Convertの前後に文字列が付与されています。

 

これを回避する方法として、関数全体をextern "C"で囲って名前修飾させないようにする(C言語の名前で関数名を構築)のが一般的なようです。

#include "svdpi.h"

#ifdef __cplusplus
extern "C" {
#endif

int Convert(
 const svOpenArrayHandle in_img,
       svOpenArrayHandle out_img
){
......

 return(0);
}

#ifdef __cplusplus
}
#endif

nmでシンボルリストを見ると余計な文字列が付いていませんでした。

$ nm refc.so
00000000000093da T Convert
.............

これで無事にSystemVerilogからコールすることができるようになりました。

 

ちなみにライブラリを作る時のMakefikeはこんな感じにしています。

refc_src = refc.cpp
refc_obj = $(refc_src:%.cpp=%.o)
refc_so  = refc.so

%.o: %.cpp
	g++ -m64 -fPIC -I$(VCS_HOME)/include -I$(refc_dir) -o $@ -c $<

$(refc_so): $(refc_obj)
	g++ -m64 -shared -o $(refc_so) $(refc_obj)