|
|
|
|
|
|
|
|
|
|
|
Verilog Procedural Interface (VPI)
|
|
|
The Verilog Procedural Interface (VPI) is a C-programming interface for the Verilog Hardware Description Language (HDL). VPI is the third-generation procedural interface to Verilog HDL. VPI provides consistent, object-oriented access to the complete Verilog HDL. |
|
|
|
|
|
VPI consists of a set of access and utility routines that you call from standard C programming language functions. These routines interact with the instantiated simulation objects contained in your Verilog HDL design. |
|
|
|
|
|
VPI is the same as Verilog PLI 1.0 and PLI 2.0, so if something is working in PLI 2.0, it can be easily ported to VPI. VPI is cleaner than earlier PLI 2.0. All the functions and tasks start with vpi_*. Example vpi_printf(). |
|
|
|
|
|
Steps : Writing Application Using VPI
|
|
|
Following steps need to be performed to write a C application and interface with Verilog simulator. |
|
|
|
|
|
- Writing a C function
- Associating C Functions with a New System Task
- Registering New System Tasks
- Invoking System Tasks
|
|
|
|
|
|
Write a C function
|
|
|
Writing C function/routine is the same as in PLI 2.0; the only difference is that we need to include vpi_user.h instead of acc_user.h and veriuser.h. Also we use vpi_* functions to access and modify objects in Verilog simulator. |
|
|
|
|
|
Below is an example code of a simple C function: |
|
|
|
|
|
1 #include "vpi_user.h"
2
3 void hello() {
4 vpi_printf("\n\nHello Deepak\n\n");
5 }
You could download file hello_vpi.c here
|
|
|
|
|
|
Associating C Functions with a New System Task
|
|
|
To associate your C function with a system task, create a data structure of type s_vpi_systf_data and a pointer to that structure. The vpi_systf_data data type is defined in the vpi_user.h include file. Below is the data structure of s_vpi_systf_data. |
|
|
|
|
|
1 typedef struct t_vpi_systf_data {
2 PLI_INT32 type; // vpiSysTask, vpiSysFunc
3 PLI_INT32 sysfunctype; // vpiSysTask, vpi[Int,Real,Time,Sized, SizedSigned]Func
4 PLI_BYTE8 *tfname; // First character must be `$'
5 PLI_INT32 (*calltf)(PLI_BYTE8 *);
6 PLI_INT32 (*compiletf)(PLI_BYTE8 *);
7 PLI_INT32 (*sizetf)(PLI_BYTE8 *); // For sized function callbacks only
8 PLI_BYTE8 *user_data;
9 } s_vpi_systf_data, *p_vpi_systf_data;
You could download file s_vpi_systf_data.h here
|
|
|
|
|
|
Field Name
|
Field Description
|
type
|
task - does not return a value; function - can return a value.
|
sysfunctype
|
If type is function, sysfunctype indicates the type of the value that the calltf function returns.
|
tfname
|
This quoted literal string defines the name of the system task or function. The first character must be $.
|
calltf
|
This field is a pointer to your application routine
|
compiletf
|
This field is a pointer to a routine that the simulator calls once each time it compiles an instance of the task or function. Enter NULL if you have no such routine.
|
sizetf
|
This field is a pointer to a routine that returns the size, in bits, of the value that the system task or function returns.
|
user_data
|
This field is a pointer to optional data. You can retrieve this data by calling the vpi_get_systf_info() routine.
|
|
|
|
|
|
|
Example for hello routine |
|
|
|
|
|
1 #include "hello_vpi.c"
2
3 // Associate C Function with a New System Task
4 void registerHelloSystfs() {
5 s_vpi_systf_data task_data_s;
6 p_vpi_systf_data task_data_p = &task_data_s;
7 task_data_p->type = vpiSysTask;
8 task_data_p->tfname = "$hello";
9 task_data_p->calltf = hello;
10 task_data_p->compiletf = 0;
11
12 vpi_register_systf(task_data_p);
13 }
14
15 // Register the new system task here
16 void (*vlog_startup_routines[ ] ) () = {
17 registerHelloSystfs,
18 0 // last entry must be 0
19 };
You could download file hello_vpi_modelsim.c here
|
|
|
|
|
|
|
|
|
|
|
|
Registering New System Tasks
|
|
|
After you initialize the s_vpi_systf_data data structure, you must register your new system task so that the simulator can execute it. In the above example of hello routine, line numbers 14 to 17 do this. |
|
|
|
|
|
Invoking System Tasks
|
|
|
You can call your new system tasks in initial blocks or in always blocks as shown below. |
|
|
|
|
|
1 module hello_pli ();
2
3 initial begin
4 $hello;
5 #10 $finish;
6 end
7
8 endmodule
You could download file hello_pli.v here
|
|
|
|
|
|
Linking with Simulator
|
|
|
Like PLI1.0 and PLI2.0, each simulator has its own way of linking VPI routines into simulator. We will see following simulators as examples: |
|
|
|
|
|
|
|
|
|
|
|
VCS
|
|
|
With VCS simulator you need to create a tab file. For our example the tab file looks like: |
|
|
|
|
|
$hello call=hello |
|
|
|
|
|
Here $hello is the name of the user defined function that will be used in Verilog code; call=hello is the C function which will be called when $hello is called in Verilog. |
|
|
|
|
|
Command line options for compiling the code is: |
|
|
|
|
|
vcs -R -P hello.tab hello_vpi.c hello_pli.v +vpi -CFLAGS "-I$VCS_HOME/`vcs -platform`/lib" |
|
|
|
|
|
The only difference between VPI and PLI command line is the option +vpi. |
|
|
|
|
|
Modelsim
|
|
|
Like VCS, modelsim simulator has its own way for communicating with PLI. We need to create a function listing all user defined functions that will be referred in Verilog and the corresponding C function to call. Unlike VCS, we need to do it in a C file as shown below. We discussed it already in "Associating C Functions with a New System Task". |
|
|
|
|
|
1 #include "hello_vpi.c"
2
3 // Associate C Function with a New System Task
4 void registerHelloSystfs() {
5 s_vpi_systf_data task_data_s;
6 p_vpi_systf_data task_data_p = &task_data_s;
7 task_data_p->type = vpiSysTask;
8 task_data_p->tfname = "$hello";
9 task_data_p->calltf = hello;
10 task_data_p->compiletf = 0;
11
12 vpi_register_systf(task_data_p);
13 }
14
15 // Register the new system task here
16 void (*vlog_startup_routines[ ] ) () = {
17 registerHelloSystfs,
18 0 // last entry must be 0
19 };
You could download file hello_vpi_modelsim.c here
|
|
|
|
|
|
vlib work |
|
|
vlog hello_pli.v |
|
|
gcc -c -g -I$MODEL/include hello_vpi_modelsim.c |
|
|
ld -shared -E -o hello_vpi.sl hello_vpi_modelsim.o |
|
|
vsim -c hello_pli -pli hello_vpi.sl |
|
|
|
|
|
In vsim command line, type "run -all" to start the simulation. |
|
|
|
|
|
Refer to modelsim user guide for details. |
|
|
|
|
|
NCSim
|
|
|
Compiling and linking for ncsim is somewhat close to modelsim. Unlike modelsim NCSim supports many ways to link. Below is the list of steps to perform. |
|
|
|
|
|
gcc -c -g -I$CDS_INST_DIR/tools/include hello_vpi_modelsim.c |
|
|
ld -shared -E -o libvpi.so hello_vpi_modelsim.o |
|
|
ncverilog hello_pli.v |
|
|
|
|
|
Refer to NCSim or NCVerilog user manual for detail on linking VPI. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|