Verilogシミュレーター「OSS CVC」のDPI機能を試す。

##はじめに
[前回](http://qiita.com/tethys_seesaa/items/e520a144243fae8d5b19)紹介したVerilogシミュレーター「OSS CVC」の機能を一つであるDPIを簡単に試してみたいと思います。

##DPIって？
SystemVerilogの機能で、SystemVerilog側からC言語の関数をコールしたり(`import`)、またその逆も出来ます(`export`)。
例えば、`import`を使用してC言語のリファレンスモデルと比較したり、`export`を使用して、ソフトウェアからハードウェアにアクセスするような開発が可能となります。
今回は、`import`のごく簡単な記述でOSS CVCを使い、SystemVerilog側からC言語関数を呼び出してみました。

##環境
こんな感じです。

```shell-session
├── Makefile
├── src
│   └── tb.c
└── tb
    └── tb.sv
```

編集と実行は、[SublimeText](http://qiita.com/tethys_seesaa/items/1676b19e7f276e94f826)を使用しました。

###tb.c

「C_add」ごく普通の足し算です。結果を標準出力に出します。キャリーとか特に考慮していません。

```c:tb.c
#include <stdio.h>
#include "svdpi.h"

void C_add(
  const svLogicVecVal* a,
  const svLogicVecVal* b,
  svLogicVecVal* c
  ) {

  c->aval = a->aval + b->aval;
  c->bval = 0;

  printf("[C] %1d\n", c->aval);

}
```

`svLogicVecVal`はVerilogの4値をCの2値で扱うための型で、`svdpi.h`で定義されています。
中身は二つの符号無し32bit `int`型である`aval`と`bval`メンバとする構造体で、以下のような対応でVerilogの4値を表現します。

| 4値 | bval | aval |
|:----|:----|:----|
| 0   | 0 | 0 |
| 1   | 0 | 1 |
| z   | 1 | 0 |
| x   | 1 | 1 |
なお、シミュレータによっては`aval` `bval`がそれぞれ`a` `b`と省略されている場合がありますので注意下さい。

###tb.sv

8bit同士の信号を足し算をC言語から呼び出し、値を表示します。C言語関数をSystemVerilogから呼び出すには、`import "DPI-C"`で関数をVerilogの`function`として扱います。`function`として`import`するには`pure`と`context`という二通りの方法がありますが、この例ではどちらでも構いません。

```sv:tb.sv
module tb();

  localparam logic [7:0] LP_A = 8'd1;
  localparam logic [7:0] LP_B = 8'd2;

  logic [7:0] x, y, z;

  import "DPI-C" pure function void C_add(
    input  logic [7:0] a, b,
    output logic [7:0] c
  );

  function void print (input logic [7:0] n);
    $display("[V] %1d", n);
  endfunction

  task set_value(output logic [7:0] a, b);
    a = LP_A;
    b = LP_B;
  endtask

  initial begin
    z = '0;
    set_value(x, y);
    C_add(x, y ,z);
    print(z);
    $finish(1);
  end

endmodule
```
本当は、`typedef`を使用してスッキリ書きたかったのですが、どうもOSS CVCは`typedef`未対応のようです…。

###Makefile

シミュレーション実行にはMakefileを今回は使用します。OSS CVCはCコードをgccでコンパイルしてダイナミックリンクライブラリ作成し、OSS CVCはそのライブラリを参照してSystemVerilogコードをコンパイルします。


```mf:Makefile
WARNS  = -Wall

INCS   = -I /usr/local/tachyon/open-src-cvc.700c/pli_incs
CPATH  = ./src
VPATH  = ./tb

CFLAGS = -fPIC -Wall -g $(INCS)
LFLAGS = -G -shared

CC      = gcc
CVC     = cvc64
OBJ     = simv

run : cvc

tb.o: $(CPATH)/tb.c
	$(CC) $(CFLAGS) -c $(CPATH)/tb.c

tb.so: tb.o
	$(LD) $(LFLAGS) tb.o -o tb.so

cvc: tb.so
	${CVC} -q -sv -sv_lib tb.so ${VPATH}/tb.sv -o $(OBJ)

run: cvc
	./$(OBJ)

clean:
	rm -rf *.o *.so *.log simv
```

Sublime Text上でビルドする環境を作成します。

```json
{
  "shell_cmd": "make"
}
```

##実行結果

Sublime Textから`ctrl`+ `b`で実行します。

```shell-session
gcc -fPIC -Wall -g -I /usr/tools/tachyon/open-src-cvc.700c/pli_incs -c ./src/tb.c
ld -G -shared tb.o -o tb.so
cvc64 -q -sv -sv_lib tb.so ./tb/tb.sv -o simv
Copyright (c) 1991-2014 Tachyon Design Automation Corp.
  All Rights reserved.  Licensed software subject to prohibitions and
  restrictions.  See OSS CVC artistic license included with release.
./simv
Copyright (c) 1991-2014 Tachyon Design Automation Corp.
  All Rights reserved.  Licensed software subject to prohibitions and
  restrictions.  See OSS CVC artistic license included with release.
[C] 3
[V] 3
```

スナップショット的にはこんな感じです。![exe.png](https://qiita-image-store.s3.amazonaws.com/0/32925/723d794b-bb85-a925-e235-a2bd59d24bfd.png)

##おわりに
OSS CVCで少なくとも`import`でDPI機能が使えることがわかりました。次のバージョンアップがいつになるかわかりませんが、それまで、`export`を使うようなコードを起こしつつ待ちたいと思います。