Veritak だったり GPL Cver だったり、 いろんな環境で Verilog HDL のシミュレーションするので、 VPI のソースも共通にできたらいいなと。
Veritak2 では VPI のサポートコンパイラは Visual C++ ということに なってるみたいですが、GCC ではだめなのかなと。
そういうことを調べた結果です。
いきなりソースです (test.c)
// ※ VERITAK の場合、アライメントを 4 にしておかないと
// 引数の受け渡しなどがうまくできないみたい
#ifdef VERITAK
#pragma pack(push,4)
#endif
// ※ このへんは自分が必要なインクルードファイルを指定
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// ※ VERITAK / CVER の配布ファイルに含まれている
// インクルードファイルが必要
#include <vpi_user.h>
// ※ さらに CVER の場合は下記ファイルも
#ifdef CVER
#include <cv_vpi_user.h>
#endif
// ※ Prototype 宣言
PLI_INT32 vpi_test(void);
extern void register_my_systfs(void);
// ※ CVER の場合は下記も
#ifdef CVER
void vpi_compat_bootstrap(void);
#endif
#ifdef VERITAK
#pragma pack(pop)
#endif
// ※ ここから VPI で呼び出す関数を自分の好きなように
PLI_INT32 vpi_test() {
vpiHandle href, iter, inh, outh;
s_vpi_value inval, outval;
int din, dout;
// ※ 引数の受け渡し
href = vpi_handle(vpiSysTfCall, NULL);
iter = vpi_iterate(vpiArgument, href);
// 引数の個数分だけ vpi_scan する
inh = vpi_scan(iter);
outh = vpi_scan(iter);
// ※ 値の読み出し方
inval.format = vpiIntVal;
vpi_get_value(inh, &inval);
din = inval.value.integer;
// ※ 実際の処理、サンプルとして SQRT を求めてみた
dout = sqrt(din);
// ※ 値の書き出し方
outval.format = vpiIntVal;
outval.value.integer = dout;
vpi_put_value(outh, &outval, NULL, vpiNoDelay);
return 0;
}
// ※ 関数の登録方法
void register_my_systfs() {
p_vpi_systf_data systf_data_p;
static s_vpi_systf_data systf_data_list[] = {
{vpiSysTask, 0, "$vpi_test", vpi_test, NULL, NULL, NULL},
// ここにいくつでも並べられる
// 0 で終わり
{0, 0, NULL, NULL, NULL, NULL, NULL}
};
systf_data_p = &(systf_data_list[0]);
while(systf_data_p->type != 0) vpi_register_systf(systf_data_p++);
}
#ifdef VERITAK
// ※ DLL の登録
__declspec(dllexport) void (*vlog_startup_routines[])() = {
register_my_systfs,
0
};
#endif
#ifdef CVER
// ※ CVER の場合
void (*vlog_startup_routines[])() = {
register_my_systfs,
0
};
void vpi_compat_bootstrap() {
int i;
for(i=0; ; i++) {
if(vlog_startup_routines[i] == NULL) break;
vlog_startup_routines[i]();
}
}
#endif
|
共有ライブラリを作ります
Windows の場合は Cygwin 上で libtest.dll を
Linux の場合は libtest.so を
MacOS X の場合は libtest.dylib を作ることになります
ちなみに Cygwin 上で GPL Cver を build する場合、普通に src dir で make -f makefile.cygwin しただけではダメで、objs dir に入って make -f makefile.dll dll exe する必要があります
で、こんな感じの Makefile になりました
# ここの名前をターゲットに合わせて変更 TARGET=test # GPL Cver に付属のインクルードファイルの置き場所 CVERINC=/usr/local/include/cver # Cygwin の場合 CC=gcc CFLAGS=-I$(CVERINC) -DCVER LDFLAGS=-shared -Wl,--out-implib=lib$(TARGET).dll.a -Wl,--export-all -Wl,--enable-auto-image-base -Wl,--export-dynamic -Wl,--output-def=lib$(TARGET).def -lcver LIBSFX=dll # Linux の場合 #CC=gcc #CFLAGS=-fPIC -Wall -g -I$(CVERINC) -DCVER #LDFLAGS=-shared --export-dynamic #LIBSFX=so # MacOS X の場合 #CC=gcc #CFLAGS=-I$(CVERINC) -fPIC -Wall -dynamic -fno-common -DCVER #LDFLAGS=-flat_namespace -bundle -undefined suppress #LIBSFX=dylib all: lib$(TARGET).$(LIBSFX) $(TARGET).o: $(TARGET).c $(CC) $(CFLAGS) -DCVER -c $(TARGET).c lib$(TARGET).$(LIBSFX): $(TARGET).o $(CC) $(TARGET).o $(LDFLAGS) -o lib$(TARGET).$(LIBSFX) |
まずは veritak2.lib を gcc から使える形式に変換するために、mingw-utils に含まれるツールを使います
reimp veritak2.lib |
これで libveritak2.a というファイルができます
これ以降の処理は MinGW でも Cygwin でも OK
Makefile はこんな感じ (Cygwin)
MinGW の場合は -mno-cygwin がいらないだけで同じ(と思う)
test.dll というファイルができます
# ここの名前をターゲットに合わせて変更 TARGET=test # Veritak に付属のインクルードファイルの置き場所 VTKINC=. CC=gcc CFLAGS=-mrtd -I$(VTKINC) -mno-cygwin -mwindows -DVERITAK DLLFLAGS=--export-all-symbols --dllname $(TARGET).dll --output-def $(TARGET).def --add-stdcall-alias --target i386-mingw32 -mno-cygwin -mwindow LIBS=-lveritak2 -L. all: $(TARGET).dll $(TARGET).o: $(TARGET).c $(CC) $(CFLAGS) -c $(TARGET).c $(TARGET).dll: $(TARGET).o dllwrap $(DLLFLAGS) $(TARGET).o $(LIBS) |
こんなベンチを書いてみました
入力データの sqrt() が表示されれば成功
module test();
reg signed [31:0] DIN;
wire signed [31:0] DOUT;
integer i;
initial begin
#10 DIN = 32'sd0;
for(i=0; i<20; i=i+1) begin
#10 DIN = DIN + 32'sd1000;
#10 $vpi_test(DIN, DOUT);
#10 $display("SQRT(%d) = %d", DIN, DOUT);
end
end
endmodule
|
GPL Cver の場合は
cver +loadvpi=libtest.dll:vpi_compat_bootstrap test.v |
Veritak の場合はプロジェクトファイルに test.v と test.dll を登録してシミュレーション開始