無償ツールで実践する「ハード・ソフト協調検証」(1) ―― SystemVerilogのDPI-C機能

Verification Enginnerの戯言

tag: 半導体

技術解説 2009年12月 6日

1.DPI-Cは,なぜ重要なのか?

 本稿で利用するSystemVerilogのDPI-Cについては,EDAベンダのセミナや書籍,Webなどではあまり紹介されていません.しかし筆者は,DPI-Cは検証において非常に有用な機能だと思っています.

 Verilog HDLでは,C言語を使うためにPLIとVPIという二つの機能を用意しています.PLIやVPIはVerilog HDLでは実現できない(実現するのが難しい)ことをC言語で実現するためのものです.例えばゲート・レベル・シミュレーションでSDFファイルから遅延情報を取り込んだり,波形表示ツールとのインターフェースを実現するのによく使われてきました(最近ではシミュレーション速度を上げるために,PLIやVPIを使わず,ダイレクト接続という方法でインターフェースを取っているものが増えている).

 PLIやVPIが一般に知られていないのは,使うための段取りが非常に面倒だからです.また,Verilog HDLの教科書や参考書は多くても,PLIやVPIの日本語の教科書や参考書は皆無に等しいことも影響しています.

 このように実際に使う側から見て,PLIやVPIは非常に取り組みにくい側面がありました.一方,DPI-Cは,PLIやVPIのような使うための段取りがほとんど必要ありません.また,PLIやVPIでは,Verilog HDL側からC言語を呼ぶための機能を提供するだけでしたが,DPI-Cでは,C言語からSystemVerilogのtaskやfunctionにアクセスできます.筆者は,この機能がDPI-Cを使う最大のメリットであると考えています.

 

2.DPI-Cとは?

 では,DPI-Cとはどのようなものなのでしょう?

 DPIはDirect Programming Interfaceの略で,SystemVerilogと外部言語の間のインターフェスを可能にするためのものです.DPIを使うには,SystemVerilogコードと外部言語コードの2種類が必要になります.SystemVerilogコードをSystemVerilogレイヤと呼び,外部言語コードを外部言語レイヤと呼びます.外部言語レイヤは各言語ごとに定義しています.

 SystemVerilogがIEEEによって標準化される前の規格である「SystemVerilog 3.1a」では,C言語を外部言語として定義したCレイヤのみを定義していました.標準化された「IEEE 1800-2005」では,C言語のDPIをDPI-Cとして定義しています.本稿でもIEEE 1800-2005の定義に従って,DPIではなく,DPI-Cの名称を使っています.

 DPI-Cを使うためには,SystemVerilogレイヤとCレイヤにそれぞれコードが必要になりますが,PLIやVPIと比べると非常に簡便に使うことができます.SystemVerilogレイヤでは2種類の宣言,すなわちSystemVerilogコードからC言語コードの関数を使うためのimport宣言と,C言語コードからSystemVerilogコードのtaskやfunctionを使うためのexport宣言があります.

  • SystemVerilogコードからC言語コードを使うときの宣言

  import "DPI-C"

    ※SystemVerilog 3.1a ではimport "DPI" だった

  • C言語コードからSystemVerilogコードのtaskやfunctionを使うときの宣言

  export "DPI-C"

    ※SystemVerilog 3.1a ではexport "DPI" だった

 import宣言は,taskとfunctionの2種類に分類できます.taskとfunctionの違いはSystemVerilogと同じで,シミュレーション時間が進むかどうかです.また,functionはpureとcontextに分類できます.pureあるいはcontextは,"DPI-C"とfunctionの間に入れます.pureはC言語側でSystemVerilogコードにアクセスしない場合にのみ使用できます.SystemVerilogコードにアクセスする場合やPLI/VPIの関数を使う場合は,pureではなくcontextを付けます.taskの場合は必ずcontextになりますが,contextを省略することができます.

  import "DPI-C" pure function int a_x(int k );
  import "DPI-C" context function void b_y(chandle h );
  import "DPI-C" task c_z( input s, output t );

 import "DPI-C" 部分以外は,通常のSystemVerilogコードと同じです.import "DPI-C"で宣言したtaskあるいはfunctionは,宣言したmoduleやprogramでのみ使うことができます.つまり,SystemVerilogのmodule/program内で定義するtaskやfunctionと同様に扱えるということです.

 一方,export宣言はSystemVerilogコードにあるfunctionやtaskをC言語コードで使うためのもので,import宣言よりも簡単です.

  export "DPI-C" function sv_func_a;
  export "DPI-C" task sv_task_b;

 functionやtaskの区別は必要ですが,import宣言のようにpureやcontextの区別,functionの戻り型,引き数(型や数)を指定する必要はありません.これは,export宣言しているmoduleあるいはprogram内で定義されているfunctionやtaskから戻り値や引き数を知ることができるので,わざわざ指定する必要がないからです.

 ただし,C言語コードでexport宣言したfunctionやtaskの戻り値や引き数が正しくないと,シミュレータでSegmentation faultなどのエラーが発生する場合があるので注意してください.シミュレータによっては,export宣言を行っているfunctionやtaskに対するC言語コードの宣言文を自動的に生成してくれるオプションなどがあります.マニュアルなどで確認してみてください.

 import宣言のfunctionで戻り値として使えるもの(SystemVerilogの型)は,void,byte,shortint,int,longint,real,shortreal,chandle,stringで,それぞれC言語のvoid,char,short,int,long long,double,float,void *,char * に対応します.functionやtaskへの引き数は,functionの戻り値と同様な型が指定できます.また,引き数については,その引き数がfunctionやtaskへの入力,出力,入出力になるかを示すために,input,output,inoutを指定できます.指定しないときは,inputが指定されているものとします.

 最後に一つ注意しなければならない点を挙げておきます.import宣言においてtaskを指定した場合のC言語コードでの関数の戻り値の型は,常にintになります.また,通常は戻り値を0とします.taskなので戻り値が必要ないと思い,C言語コードの関数の戻り値の型をvoidにすると,シミュレーション実行時に正しく動作しなかったり,エラーが発生する場合があります.


(第2回の記事はこちら

Verification Enginnerの戯言
http://blogs.yahoo.co.jp/verification_engineer


 

«  1  2
組み込みキャッチアップ

お知らせ 一覧を見る

電子書籍の最新刊! FPGAマガジン No.12『ARMコアFPGA×Linux初体験』好評発売中

FPGAマガジン No.11『性能UP! アルゴリズム×手仕上げHDL』好評発売中! PDF版もあります

PICK UP用語

EV(電気自動車)

関連記事

EnOcean

関連記事

Android

関連記事

ニュース 一覧を見る
Tech Villageブログ

渡辺のぼるのロボコン・プロモータ日記

2年ぶりのブログ更新w

2016年10月 9日

Hamana Project

Hamana-8最終打ち上げ報告(その2)

2012年6月26日