La interfaz procedimental Verilog (VPI), conocida originalmente como PLI 2.0, es una interfaz pensada principalmente para el lenguaje de programación C. Permite que el código de comportamiento Verilog invoque funciones C, y que las funciones C invoquen tareas estándar del sistema Verilog. La interfaz procedimental Verilog forma parte del estándar IEEE 1364 Programming Language Interface; la edición más reciente del estándar es de 2005. A veces, a VPI también se la denomina PLI 2, ya que reemplaza a la obsoleta Program Language Interface (PLI) .
Si bien PLI 1 quedó obsoleto en favor de VPI (también conocido como PLI 2), PLI 1 todavía se usa comúnmente en lugar de VPI debido a su interfaz de función tf_put, tf_get mucho más ampliamente documentada que se describe en muchos libros de referencia de verilog.
C++ se puede integrar con VPI (PLI 2.0) y PLI 1.0, utilizando la palabra clave "extern C/C++" incorporada en los compiladores de C++.
Como ejemplo, considere el siguiente fragmento de código Verilog:
valor = 41;$incremento(val);$display("Después de $incremento, val=%d", val);
Supongamos que la increment
tarea del sistema incrementa su primer parámetro en uno. Utilizando C y el mecanismo VPI, la increment
tarea se puede implementar de la siguiente manera:
// Implementa la tarea del sistema de incremento static int increment ( char * userdata ) { vpiHandle systfref , args_iter , argh ; struct t_vpi_value argval ; int value ; // Obtener un identificador para la lista de argumentos systfref = vpi_handle ( vpiSysTfCall , NULL ); args_iter = vpi_iterate ( vpiArgument , systfref ); // Toma el valor del primer argumento argh = vpi_scan ( args_iter ); argval.format = vpiIntVal ; vpi_get_value ( argh , & argval ); value = argval.value.integer ; vpi_printf ( " La rutina VPI recibió % d \ n " , value ) ; // Incrementa el valor y vuelve a colocarlo como primer argumento argval . value . entire = value + 1 ; vpi_put_value ( argh , & argval , NULL , vpiNoDelay ); // Limpieza y retorno vpi_free_object ( args_iter ); return 0 ; }
Además, es necesaria una función que registre esta tarea del sistema. Esta función se invoca antes de la elaboración o resolución de referencias cuando se coloca en la vlog_startup_routines[]
matriz visible externamente.
// Registra la tarea del sistema de incremento void register_increment () { s_vpi_systf_data data = { vpiSysTask , 0 , "$increment" , increment , 0 , 0 , 0 }; vpi_register_systf ( & data ); } // Contiene una lista terminada en cero de funciones que deben llamarse al inicio void ( * vlog_startup_routines [])() = { register_increment , 0 };
El código C se compila en un objeto compartido que utilizará el simulador Verilog. Una simulación del fragmento Verilog mencionado anteriormente dará como resultado lo siguiente:
Rutina VPI recibida 41Después de $increment, val=42