2009年6月5日 星期五

如何使用C開發Verilog System Task/Function? (SOC) (Verilog) (Verilog PLI)

如何使用C開發Verilog System Task/Function? (SOC) (Verilog) (Verilog PLI)


Abstract
本文介紹使用C開發Verilog System task/function,以彌補Verilog功能的不足。

Introduction
使用環境 : Cadense NC-Verilog 5.4 + Visual C++ 6.0

Verilog PLI(Programming Language Interface)是Verilog所提供的機制,我們可以使用C語言開發自己的system task/function,以彌補在Verilog撰寫testbench的不足。

在此文件,將學習到:
1.如何在Verilog呼叫C function?
2.如何撰寫簡單的calltf routine與register function?
3.如何在Windows平台使用Cadence NC-Verilog編譯與連結?

如下圖所示,當simulator執行自己開發的system task時,會轉而執行C的function,執行完再回到Verilog。

pli_flow

使用C開發Verilog system task的流程如下圖所示:

pli_hello_world01

Step 1:
建立C function

Step 2:
建立C function與Verilog system task的連結資料

hello_world.c / C

1 #include <stdio.h> // define NULL, printf()
2 #include "vpi_user.h" // required by VPI application
3
4 // my own C function for Verilog
5 PLI_INT32 hello_world(PLI_BYTE8 *user_data) {
6 vpi_printf("Hello World from C!!\n");
7
8 return 0;
9 }
10
11 // defined in vpi_user.h
12 /*
13 typedef struct t_vpi_systf_data {
14 PLI_INT32 type; // vpiSysTask, vpiSysFunc
15 PLI_INT32 sysfunctype; // vpiSysTask, vpi[Int,Real,Time,Sized, SizedSigned]Func
16 PLI_BYTE8 *tfname; // first character must be `$'
17 PLI_INT32 (*calltf)(PLI_BYTE8 *);
18 PLI_INT32 (*compiletf)(PLI_BYTE8 *);
19 PLI_INT32 (*sizetf)(PLI_BYTE8 *); // for sized function callbacks only
20 PLI_BYTE8 *user_data;
21 } s_vpi_systf_data, *p_vpi_systf_data;
22 */
23
24 // associating C function with new verilog system task
25 // you can use your favorite function name
26 void register_my_systfs() {
27 s_vpi_systf_data tf_data; // defined in vpi_user.h
28
29 tf_data.type = vpiSysTask; // system task
30 tf_data.tfname = "$hello_world"; // name of system task
31 tf_data.calltf = hello_world; // C function name
32 tf_data.compiletf = NULL; // no compiletf routine
33
34 vpi_register_systf(&tf_data); // register system task to verilog
35 }


第2行

#include "vpi_user.h" // required by VPI application


寫PLI一定要include。

第4行

// my own C function for Verilog
PLI_INT32 hello_world(PLI_BYTE8 *user_data) {
vpi_printf(
"Hello World from C!!\n");

return 0;
}


自己的C function,僅簡單的顯示Hello World。由於struct s_vpi_systf_data規定自訂的C function的signature必須為PLI_INT32 (*calltf)(PLI_BYTE8 *),所以依照其規定宣告hello_world型別。

24行

// associating C function with new verilog system task
// you can use your favorite function name
void register_my_systfs() {
s_vpi_systf_data tf_data;
// defined in vpi_user.h

tf_data.type
= vpiSysTask; // system task
tf_data.tfname = "$hello_world"; // name of system task
tf_data.calltf = hello_world; // C function name
tf_data.compiletf = NULL; // no compiletf routine

vpi_register_systf(
&tf_data); // register system task to verilog
}


建立C function與Verilog system task的連結資料,s_vpi_systf_data定義在vpi_user.h,其完整定義如下:

typedef struct t_vpi_systf_data {
PLI_INT32 type;
// vpiSysTask, vpiSysFunc
PLI_INT32 sysfunctype; // vpiSysTask, vpi[Int,Real,Time,Sized, SizedSigned]Func
PLI_BYTE8 *tfname; // first character must be `$'
PLI_INT32 (*calltf)(PLI_BYTE8 *);
PLI_INT32 (
*compiletf)(PLI_BYTE8 *);
PLI_INT32 (
*sizetf)(PLI_BYTE8 *); // for sized function callbacks only
PLI_BYTE8 *user_data;
} s_vpi_systf_data,
*p_vpi_systf_data;


register_my_systfs() function主要的目的在於將s_vpi_systf_data struct填滿, 名稱不一定要取register_my_systfs,可以自行命名。

29行

tf_data.type = vpiSysTask; // system task


定義為System Task。

30行

tf_data.tfname = "$hello_world"; // name of system task


定義Verilog system task名稱

31行

tf_data.calltf = hello_world; // C function name


指定自己寫的C function名稱,為function pointer,為了callback使用。

32行

tf_data.compiletf = NULL; // no compiletf routine


由於沒用到compiletf,所以設定為NULL。

34行

vpi_register_systf(&tf_data); // register system task to verilog


註冊新的system task。

Step 3:
在simulator註冊新Verilog system task

複製C:\Program Files\Cadence Design Systems\IUS\tools\src\vpi_user.c到目前目錄,將vpi_user.c修改如下:

1 /*
2 * |-----------------------------------------------------------------------|
3 * | |
4 * | Copyright Cadence Design Systems, Inc. 1985, 1988. |
5 * | All Rights Reserved. Licensed Software. |
6 * | |
7 * | |
8 * | THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF CADENCE DESIGN SYSTEMS |
9 * | The copyright notice above does not evidence any actual or intended |
10 * | publication of such source code. |
11 * | |
12 * |-----------------------------------------------------------------------|
13 */
14
15 /*
16 * |-------------------------------------------------------------|
17 * | |
18 * | PROPRIETARY INFORMATION, PROPERTY OF CADENCE DESIGN SYSTEMS |
19 * | |
20 * |-------------------------------------------------------------|
21 */
22
23 #include <stdarg.h>
24 #include "vpi_user.h"
25 #include "vpi_user_cds.h"
26
27
28 /* extern void setup_test_callbacks();*/
29
30 /* ----------------------------------------------------------------
31 The following is an example of what should be included in this file:
32
33 extern void setup_my_callbacks(); <-- Add a declaration for your routine.
34
35 void (*vlog_startup_routines[])() =
36 {
37 $*** add user entries here ***$
38
39 setup_my_callbacks, <-- Add your routine to the table.
40
41 0 $*** final entry must be 0 ***$
42
43 };
44 ------------------------------------------------------------------ */
45
46 extern void register_my_systfs();
47
48 void (*vlog_startup_routines[VPI_MAXARRAY])() =
49 {
50 register_my_systfs,
51 0 /*** final entry must be 0 ***/
52 };


46行

extern void register_my_systfs();


使用extern宣告在hello_world.c的register_my_systfs。

48行

void (*vlog_startup_routines[VPI_MAXARRAY])() =
{
register_my_systfs,
0 /*** final entry must be 0 ***/
};


設定simulator啟動時,載入PLI的array,注意最後一個element必須為0。

Step 4:
使用PLI Wizard產生Dynamic Link Library (libvpi.dll)

啟動PLI Wizard

開始->程式集->Cadence Design Systems->Design & Verification->PLI Wizard

File -> New Session

pli_hello_world02

選擇VPI Application與libvp

pli_hello_world03

加入hello_world.c,vpi_user.c會自動抓進來

pli_hello_world04

加入VC6的include path: C:\Program Files\Microsoft Visual Studio\VC98\Include

選擇C語言

pli_hello_world05

按Finish完成

pli_hello_world06

選(Y)

pli_hello_world07

按Close離開

pli_hello_world08

File -> Exit離開PLI Wizard

Step 5:
設定libvpi.dll路徑

在Path環境變數加上libvpi.dll的路徑,注意必須加在C:\Program Files\Cadence Design Systems\IUS\tools\bin;C:\Program Files\Cadence Design Systems\IUS\tools\lib;C:\Novas\Debussy\bin;之前,否則PLI Wizard啟動會有問題。

設定好後須登出在登入,path才會生效。

若只是為了測試,可將libvpi.dll放在與*.v同目錄下即可。

Step 6:

在Verilog使用新的system task

hello_world.v / Verilog

1 module hello_world;
2
3 initial begin
4 $hello_world;
5 #10 $finish;
6 end
7
8 endmodule


Step 7:
執行NC-Verilog

ncverilog +access+r hello_world.v


pli_hello_world09

完整程式碼下載
pli_hello_world.7z

Conclusion
PLI在Verilog的IEEE標準中有明確定義,但如何compiling與linking方面,就與simulator與OS有關,IEEE標準並沒有加以定義。本文雖然只是一個小小的Hello World,已經展示了Verilog PLI如何在Windows平台與Cadence NC-Verilog compiling與linking,並看到Verilog如何呼叫一個C的function。

沒有留言: