![]() | This article has multiple issues. Please help improve it or discuss these issues on the talk page . (Learn how and when to remove these messages)
|
The Verilog Procedural Interface (VPI), originally known as PLI 2.0, is an interface primarily intended for the C programming language. It allows behavioral Verilog code to invoke C functions, and C functions to invoke standard Verilog system tasks. The Verilog Procedural Interface is part of the IEEE 1364 Programming Language Interface standard; the most recent edition of the standard is from 2005. VPI is sometimes also referred to as PLI 2, since it replaces the deprecated Program Language Interface (PLI).
While PLI 1 was deprecated in favor of VPI (aka. PLI 2), PLI 1 is still commonly used over VPI due to its much more widely documented tf_put, tf_get function interface that is described in many verilog reference books.
C++ is integrable with VPI (PLI 2.0) and PLI 1.0, by using the "extern C/C++" keyword built into C++ compilers.
As an example, consider the following Verilog code fragment:
val = 41; $increment(val); $display("After $increment, val=%d", val);
Suppose the increment
system task increments its first parameter by one. Using C and the VPI mechanism, the increment
task can be implemented as follows:
// Implements the increment system taskstaticPLI_INT32increment(PLI_BYTE8*userdata){vpiHandlesystfref,args_iter,argh;s_vpi_valueargval;intvalue;// Obtain a handle to the argument listsystfref=vpi_handle(vpiSysTfCall,NULL);args_iter=vpi_iterate(vpiArgument,systfref);// Grab the value of the first argumentargh=vpi_scan(args_iter);argval.format=vpiIntVal;vpi_get_value(argh,&argval);value=argval.value.integer;vpi_printf("VPI routine received %d\n",value);// Increment the value and put it back as first argumentargval.value.integer=value+1;vpi_put_value(argh,&argval,NULL,vpiNoDelay);// Cleanup and returnvpi_free_object(args_iter);return0;}
Also, a function that registers this system task is necessary. This function is invoked prior to elaboration or resolution of references when it is placed in the externally visible vlog_startup_routines[]
array.
// Registers the increment system taskvoidregister_increment(void){s_vpi_systf_datadata={/* type */vpiSysTask,/* sysfunctype */vpiSysTask,/* tfname */"$increment",/* calltf */increment,/* compiletf */NULL,/* sizetf */NULL,/* user_data */NULL};vpi_register_systf(&data);}// Contains a zero-terminated list of functions that have to be called at startupvoid(*vlog_startup_routines[])(void)={register_increment,NULL};
The C code is compiled into a shared object that will be used by the Verilog simulator. A simulation of the earlier mentioned Verilog fragment will now result in the following output:
VPI routine received 41 After $increment, val=42